| __`SYSLIB0011`__ | `BinaryFormatter` serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for recommended alternatives. |
| __`SYSLIB0012`__ | Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead. |
| __`SYSLIB0013`__ | Uri.EscapeUriString can corrupt the Uri string in some cases. Consider using Uri.EscapeDataString for query string components instead. |
-| __`SYSLIB0015`__ | DisablePrivateReflectionAttribute has no effect in .NET 6.0+ applications. |
\ No newline at end of file
+| __`SYSLIB0015`__ | DisablePrivateReflectionAttribute has no effect in .NET 6.0+ applications. |
+
+### Analyzer warnings (`SYSLIB1001` - `SYSLIB1999`)
+| Diagnostic ID | Description |
+| :---------------- | :---------- |
+| __`SYSLIB1001`__ | Logging method names cannot start with _ |
+| __`SYSLIB1002`__ | Don't include log level parameters as templates in the logging message |
+| __`SYSLIB1003`__ | InvalidLoggingMethodParameterNameTitle |
+| __`SYSLIB1004`__ | Logging class cannot be in nested types |
+| __`SYSLIB1005`__ | Could not find a required type definition |
+| __`SYSLIB1006`__ | Multiple logging methods cannot use the same event id within a class |
+| __`SYSLIB1007`__ | Logging methods must return void |
+| __`SYSLIB1008`__ | One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface |
+| __`SYSLIB1009`__ | Logging methods must be static |
+| __`SYSLIB1010`__ | Logging methods must be partial |
+| __`SYSLIB1011`__ | Logging methods cannot be generic |
+| __`SYSLIB1012`__ | Redundant qualifier in logging message |
+| __`SYSLIB1013`__ | Don't include exception parameters as templates in the logging message |
+| __`SYSLIB1014`__ | Logging template has no corresponding method argument |
+| __`SYSLIB1015`__ | Argument is not referenced from the logging message |
+| __`SYSLIB1016`__ | Logging methods cannot have a body |
+| __`SYSLIB1017`__ | A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method |
+| __`SYSLIB1018`__ | Don't include logger parameters as templates in the logging message |
+| __`SYSLIB1019`__ | Couldn't find a field of type Microsoft.Extensions.Logging.ILogger |
+| __`SYSLIB1020`__ | Found multiple fields of type Microsoft.Extensions.Logging.ILogger |
+| __`SYSLIB1021`__ | Can't have the same template with different casing |
+| __`SYSLIB1022`__ | Can't have malformed format strings (like dangling {, etc) |
+| __`SYSLIB1023`__ | Generating more than 6 arguments is not supported |
+| __`SYSLIB1029`__ | *_Blocked range `SYSLIB1024`-`SYSLIB1029` for logging._* |
\ No newline at end of file
<ProjectServicingConfiguration Include="Microsoft.NETCore.App.Ref" PatchVersion="0" />
</ItemGroup>
<PropertyGroup>
+ <!-- For source generator support we need to target a pinned version in order to be able to run on older versions of Roslyn -->
+ <MicrosoftCodeAnalysisCSharpWorkspacesVersion>3.8.0</MicrosoftCodeAnalysisCSharpWorkspacesVersion>
+ <MicrosoftCodeAnalysisVersion>3.8.0</MicrosoftCodeAnalysisVersion>
+ </PropertyGroup>
+ <PropertyGroup>
<MicrosoftCodeAnalysisNetAnalyzersVersion>6.0.0-preview3.21168.1</MicrosoftCodeAnalysisNetAnalyzersVersion>
<MicrosoftCodeAnalysisCSharpCodeStyleVersion>3.9.0-5.final</MicrosoftCodeAnalysisCSharpCodeStyleVersion>
<MicrosoftCodeAnalysisCSharpVersion>3.9.0-5.final</MicrosoftCodeAnalysisCSharpVersion>
<XUnitRunnerVisualStudioVersion>2.4.2</XUnitRunnerVisualStudioVersion>
<CoverletCollectorVersion>1.3.0</CoverletCollectorVersion>
<NewtonsoftJsonVersion>12.0.3</NewtonsoftJsonVersion>
+ <SQLitePCLRawbundle_greenVersion>2.0.4</SQLitePCLRawbundle_greenVersion>
<MoqVersion>4.12.0</MoqVersion>
<FsCheckVersion>2.14.3</FsCheckVersion>
<!-- Docs -->
--- /dev/null
+// 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.Collections.Immutable;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Text;
+using Xunit;
+
+namespace SourceGenerators.Tests
+{
+ internal static class RoslynTestUtils
+ {
+ /// <summary>
+ /// Creates a canonical Roslyn project for testing.
+ /// </summary>
+ /// <param name="references">Assembly references to include in the project.</param>
+ /// <param name="includeBaseReferences">Whether to include references to the BCL assemblies.</param>
+ public static Project CreateTestProject(IEnumerable<Assembly>? references, bool includeBaseReferences = true)
+ {
+ string corelib = Assembly.GetAssembly(typeof(object))!.Location;
+ string runtimeDir = Path.GetDirectoryName(corelib)!;
+
+ var refs = new List<MetadataReference>();
+ if (includeBaseReferences)
+ {
+ refs.Add(MetadataReference.CreateFromFile(corelib));
+ refs.Add(MetadataReference.CreateFromFile(Path.Combine(runtimeDir, "netstandard.dll")));
+ refs.Add(MetadataReference.CreateFromFile(Path.Combine(runtimeDir, "System.Runtime.dll")));
+ }
+
+ if (references != null)
+ {
+ foreach (var r in references)
+ {
+ refs.Add(MetadataReference.CreateFromFile(r.Location));
+ }
+ }
+
+ return new AdhocWorkspace()
+ .AddSolution(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Create()))
+ .AddProject("Test", "test.dll", "C#")
+ .WithMetadataReferences(refs)
+ .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithNullableContextOptions(NullableContextOptions.Enable));
+ }
+
+ public static Task CommitChanges(this Project proj, params string[] ignorables)
+ {
+ Assert.True(proj.Solution.Workspace.TryApplyChanges(proj.Solution));
+ return AssertNoDiagnostic(proj, ignorables);
+ }
+
+ public static async Task AssertNoDiagnostic(this Project proj, params string[] ignorables)
+ {
+ foreach (Document doc in proj.Documents)
+ {
+ SemanticModel? sm = await doc.GetSemanticModelAsync(CancellationToken.None).ConfigureAwait(false);
+ Assert.NotNull(sm);
+
+ foreach (Diagnostic d in sm!.GetDiagnostics())
+ {
+ bool ignore = ignorables.Any(ig => d.Id == ig);
+
+ Assert.True(ignore, d.ToString());
+ }
+ }
+ }
+
+ private static Project WithDocuments(this Project project, IEnumerable<string> sources, IEnumerable<string>? sourceNames = null)
+ {
+ int count = 0;
+ Project result = project;
+ if (sourceNames != null)
+ {
+ List<string> names = sourceNames.ToList();
+ foreach (string s in sources)
+ result = result.WithDocument(names[count++], s);
+ }
+ else
+ {
+ foreach (string s in sources)
+ result = result.WithDocument($"src-{count++}.cs", s);
+ }
+
+ return result;
+ }
+
+ public static Project WithDocument(this Project proj, string name, string text)
+ {
+ return proj.AddDocument(name, text).Project;
+ }
+
+ public static Document FindDocument(this Project proj, string name)
+ {
+ foreach (Document doc in proj.Documents)
+ {
+ if (doc.Name == name)
+ {
+ return doc;
+ }
+ }
+
+ throw new FileNotFoundException(name);
+ }
+
+ /// <summary>
+ /// Looks for /*N+*/ and /*-N*/ markers in a string and creates a TextSpan containing the enclosed text.
+ /// </summary>
+ public static TextSpan MakeSpan(string text, int spanNum)
+ {
+ int start = text.IndexOf($"/*{spanNum}+*/", StringComparison.Ordinal);
+ if (start < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(spanNum));
+ }
+
+ start += 6;
+
+ int end = text.IndexOf($"/*-{spanNum}*/", StringComparison.Ordinal);
+ if (end < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(spanNum));
+ }
+
+ end -= 1;
+
+ return new TextSpan(start, end - start);
+ }
+
+ /// <summary>
+ /// Runs a Roslyn generator over a set of source files.
+ /// </summary>
+ public static async Task<(ImmutableArray<Diagnostic>, ImmutableArray<GeneratedSourceResult>)> RunGenerator(
+ ISourceGenerator generator,
+ IEnumerable<Assembly>? references,
+ IEnumerable<string> sources,
+ AnalyzerConfigOptionsProvider? optionsProvider = null,
+ bool includeBaseReferences = true,
+ CancellationToken cancellationToken = default)
+ {
+ Project proj = CreateTestProject(references, includeBaseReferences);
+
+ proj = proj.WithDocuments(sources);
+
+ Assert.True(proj.Solution.Workspace.TryApplyChanges(proj.Solution));
+
+ Compilation? comp = await proj!.GetCompilationAsync(CancellationToken.None).ConfigureAwait(false);
+
+ CSharpGeneratorDriver cgd = CSharpGeneratorDriver.Create(new[] { generator }, optionsProvider: optionsProvider);
+ GeneratorDriver gd = cgd.RunGenerators(comp!, cancellationToken);
+
+ GeneratorDriverRunResult r = gd.GetRunResult();
+ return (r.Results[0].Diagnostics, r.Results[0].GeneratedSources);
+ }
+
+ /// <summary>
+ /// Runs a Roslyn analyzer over a set of source files.
+ /// </summary>
+ public static async Task<IList<Diagnostic>> RunAnalyzer(
+ DiagnosticAnalyzer analyzer,
+ IEnumerable<Assembly> references,
+ IEnumerable<string> sources)
+ {
+ Project proj = CreateTestProject(references);
+
+ proj = proj.WithDocuments(sources);
+
+ await proj.CommitChanges().ConfigureAwait(false);
+
+ ImmutableArray<DiagnosticAnalyzer> analyzers = ImmutableArray.Create(analyzer);
+
+ Compilation? comp = await proj!.GetCompilationAsync().ConfigureAwait(false);
+ return await comp!.WithAnalyzers(analyzers).GetAllDiagnosticsAsync().ConfigureAwait(false);
+ }
+
+ /// <summary>
+ /// Runs a Roslyn analyzer and fixer.
+ /// </summary>
+ public static async Task<IList<string>> RunAnalyzerAndFixer(
+ DiagnosticAnalyzer analyzer,
+ CodeFixProvider fixer,
+ IEnumerable<Assembly> references,
+ IEnumerable<string> sources,
+ IEnumerable<string>? sourceNames = null,
+ string? defaultNamespace = null,
+ string? extraFile = null)
+ {
+ Project proj = CreateTestProject(references);
+
+ int count = sources.Count();
+ proj = proj.WithDocuments(sources, sourceNames);
+
+ if (defaultNamespace != null)
+ {
+ proj = proj.WithDefaultNamespace(defaultNamespace);
+ }
+
+ await proj.CommitChanges().ConfigureAwait(false);
+
+ ImmutableArray<DiagnosticAnalyzer> analyzers = ImmutableArray.Create(analyzer);
+
+ while (true)
+ {
+ Compilation? comp = await proj!.GetCompilationAsync().ConfigureAwait(false);
+ ImmutableArray<Diagnostic> diags = await comp!.WithAnalyzers(analyzers).GetAllDiagnosticsAsync().ConfigureAwait(false);
+ if (diags.IsEmpty)
+ {
+ // no more diagnostics reported by the analyzers
+ break;
+ }
+
+ var actions = new List<CodeAction>();
+ foreach (Diagnostic d in diags)
+ {
+ Document? doc = proj.GetDocument(d.Location.SourceTree);
+
+ CodeFixContext context = new CodeFixContext(doc!, d, (action, _) => actions.Add(action), CancellationToken.None);
+ await fixer.RegisterCodeFixesAsync(context).ConfigureAwait(false);
+ }
+
+ if (actions.Count == 0)
+ {
+ // nothing to fix
+ break;
+ }
+
+ ImmutableArray<CodeActionOperation> operations = await actions[0].GetOperationsAsync(CancellationToken.None).ConfigureAwait(false);
+ Solution solution = operations.OfType<ApplyChangesOperation>().Single().ChangedSolution;
+ Project? changedProj = solution.GetProject(proj.Id);
+ if (changedProj != proj)
+ {
+ proj = await RecreateProjectDocumentsAsync(changedProj!).ConfigureAwait(false);
+ }
+ }
+
+ var results = new List<string>();
+
+ if (sourceNames != null)
+ {
+ List<string> l = sourceNames.ToList();
+ for (int i = 0; i < count; i++)
+ {
+ SourceText s = await proj.FindDocument(l[i]).GetTextAsync().ConfigureAwait(false);
+ results.Add(s.ToString().Replace("\r\n", "\n", StringComparison.Ordinal));
+ }
+ }
+ else
+ {
+ for (int i = 0; i < count; i++)
+ {
+ SourceText s = await proj.FindDocument($"src-{i}.cs").GetTextAsync().ConfigureAwait(false);
+ results.Add(s.ToString().Replace("\r\n", "\n", StringComparison.Ordinal));
+ }
+ }
+
+ if (extraFile != null)
+ {
+ SourceText s = await proj.FindDocument(extraFile).GetTextAsync().ConfigureAwait(false);
+ results.Add(s.ToString().Replace("\r\n", "\n", StringComparison.Ordinal));
+ }
+
+ return results;
+ }
+
+ private static async Task<Project> RecreateProjectDocumentsAsync(Project project)
+ {
+ foreach (DocumentId documentId in project.DocumentIds)
+ {
+ Document? document = project.GetDocument(documentId);
+ document = await RecreateDocumentAsync(document!).ConfigureAwait(false);
+ project = document.Project;
+ }
+
+ return project;
+ }
+
+ private static async Task<Document> RecreateDocumentAsync(Document document)
+ {
+ SourceText newText = await document.GetTextAsync().ConfigureAwait(false);
+ return document.WithText(SourceText.From(newText.ToString(), newText.Encoding, newText.ChecksumAlgorithm));
+ }
+ }
+}
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{35D3ECF9-E321-4AA6-BF5B-41E7AC54A620}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{9E96ED55-37A0-4007-854D-F3E3526E3CC0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "gen\Microsoft.Extensions.Logging.Generators.csproj", "{56A5DED2-47C2-4938-931E-B896A6BDDA0D}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\ref\System.Text.Encodings.Web.csproj", "{58614FD7-05BC-46A8-900D-AC5B8622C724}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\ref\System.Text.Json.csproj", "{F7E444A4-124D-48E2-B311-17A5ED8B0CC2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Threading.AccessControl", "..\System.Threading.AccessControl\ref\System.Threading.AccessControl.csproj", "{5FF1A443-F491-428F-9121-51523AA65052}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Tests", "tests\Microsoft.Extensions.Logging.Generators.Tests\Microsoft.Extensions.Logging.Generators.Tests.csproj", "{8C0151F9-1FC9-4D9B-A5B1-60C7B8E7B761}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
{1E1B25F0-7B14-4798-BBF4-156A52949CBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E1B25F0-7B14-4798-BBF4-156A52949CBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E1B25F0-7B14-4798-BBF4-156A52949CBA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {56A5DED2-47C2-4938-931E-B896A6BDDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {56A5DED2-47C2-4938-931E-B896A6BDDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {56A5DED2-47C2-4938-931E-B896A6BDDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {56A5DED2-47C2-4938-931E-B896A6BDDA0D}.Release|Any CPU.Build.0 = Release|Any CPU
{58614FD7-05BC-46A8-900D-AC5B8622C724}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58614FD7-05BC-46A8-900D-AC5B8622C724}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58614FD7-05BC-46A8-900D-AC5B8622C724}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FF1A443-F491-428F-9121-51523AA65052}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5FF1A443-F491-428F-9121-51523AA65052}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FF1A443-F491-428F-9121-51523AA65052}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8C0151F9-1FC9-4D9B-A5B1-60C7B8E7B761}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8C0151F9-1FC9-4D9B-A5B1-60C7B8E7B761}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8C0151F9-1FC9-4D9B-A5B1-60C7B8E7B761}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8C0151F9-1FC9-4D9B-A5B1-60C7B8E7B761}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
{504464B5-B163-4D6B-A113-52DDC78A401D} = {35D3ECF9-E321-4AA6-BF5B-41E7AC54A620}
{7467E5B1-7454-4277-A84F-E8BE34A80CE4} = {62569F09-F901-4240-B3E1-E2FF90544D74}
{1E1B25F0-7B14-4798-BBF4-156A52949CBA} = {35D3ECF9-E321-4AA6-BF5B-41E7AC54A620}
+ {56A5DED2-47C2-4938-931E-B896A6BDDA0D} = {9E96ED55-37A0-4007-854D-F3E3526E3CC0}
{58614FD7-05BC-46A8-900D-AC5B8622C724} = {62569F09-F901-4240-B3E1-E2FF90544D74}
{F7E444A4-124D-48E2-B311-17A5ED8B0CC2} = {62569F09-F901-4240-B3E1-E2FF90544D74}
{5B5AFA97-C1FC-47B9-AB7A-6A10E0285282} = {62569F09-F901-4240-B3E1-E2FF90544D74}
{5FF1A443-F491-428F-9121-51523AA65052} = {62569F09-F901-4240-B3E1-E2FF90544D74}
+ {8C0151F9-1FC9-4D9B-A5B1-60C7B8E7B761} = {88957302-AFDD-4923-BF5A-336EAB5F28B7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B57B7C13-740F-4482-B7B6-B5E87014ACB1}
--- /dev/null
+// 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 Microsoft.CodeAnalysis;
+
+namespace Microsoft.Extensions.Logging.Generators
+{
+ public static class DiagnosticDescriptors
+ {
+ public static DiagnosticDescriptor InvalidLoggingMethodName { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1001",
+ title: new LocalizableResourceString(nameof(SR.InvalidLoggingMethodNameMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.InvalidLoggingMethodNameMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor ShouldntMentionLogLevelInMessage { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1002",
+ title: new LocalizableResourceString(nameof(SR.ShouldntMentionLogLevelInMessageTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.ShouldntMentionInTemplateMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor InvalidLoggingMethodParameterName { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1003",
+ title: new LocalizableResourceString(nameof(SR.InvalidLoggingMethodParameterNameMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.InvalidLoggingMethodParameterNameMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor LoggingMethodInNestedType { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1004",
+ title: new LocalizableResourceString(nameof(SR.LoggingMethodInNestedTypeMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.LoggingMethodInNestedTypeMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor MissingRequiredType { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1005",
+ title: new LocalizableResourceString(nameof(SR.MissingRequiredTypeTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.MissingRequiredTypeMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor ShouldntReuseEventIds { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1006",
+ title: new LocalizableResourceString(nameof(SR.ShouldntReuseEventIdsTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.ShouldntReuseEventIdsMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor LoggingMethodMustReturnVoid { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1007",
+ title: new LocalizableResourceString(nameof(SR.LoggingMethodMustReturnVoidMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.LoggingMethodMustReturnVoidMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor MissingLoggerArgument { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1008",
+ title: new LocalizableResourceString(nameof(SR.MissingLoggerArgumentMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.MissingLoggerArgumentMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor LoggingMethodShouldBeStatic { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1009",
+ title: new LocalizableResourceString(nameof(SR.LoggingMethodShouldBeStaticMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.LoggingMethodShouldBeStaticMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor LoggingMethodMustBePartial { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1010",
+ title: new LocalizableResourceString(nameof(SR.LoggingMethodMustBePartialMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.LoggingMethodMustBePartialMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor LoggingMethodIsGeneric { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1011",
+ title: new LocalizableResourceString(nameof(SR.LoggingMethodIsGenericMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.LoggingMethodIsGenericMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor RedundantQualifierInMessage { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1012",
+ title: new LocalizableResourceString(nameof(SR.RedundantQualifierInMessageTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.RedundantQualifierInMessageMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor ShouldntMentionExceptionInMessage { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1013",
+ title: new LocalizableResourceString(nameof(SR.ShouldntMentionExceptionInMessageTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.ShouldntMentionInTemplateMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor TemplateHasNoCorrespondingArgument { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1014",
+ title: new LocalizableResourceString(nameof(SR.TemplateHasNoCorrespondingArgumentTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.TemplateHasNoCorrespondingArgumentMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor ArgumentHasNoCorrespondingTemplate { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1015",
+ title: new LocalizableResourceString(nameof(SR.ArgumentHasNoCorrespondingTemplateTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.ArgumentHasNoCorrespondingTemplateMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor LoggingMethodHasBody { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1016",
+ title: new LocalizableResourceString(nameof(SR.LoggingMethodHasBodyMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.LoggingMethodHasBodyMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor MissingLogLevel { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1017",
+ title: new LocalizableResourceString(nameof(SR.MissingLogLevelMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.MissingLogLevelMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor ShouldntMentionLoggerInMessage { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1018",
+ title: new LocalizableResourceString(nameof(SR.ShouldntMentionLoggerInMessageTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.ShouldntMentionInTemplateMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor MissingLoggerField { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1019",
+ title: new LocalizableResourceString(nameof(SR.MissingLoggerFieldTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.MissingLoggerFieldMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor MultipleLoggerFields { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1020",
+ title: new LocalizableResourceString(nameof(SR.MultipleLoggerFieldsTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.MultipleLoggerFieldsMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor InconsistentTemplateCasing { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1021",
+ title: new LocalizableResourceString(nameof(SR.InconsistentTemplateCasingMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.InconsistentTemplateCasingMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor MalformedFormatStrings { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1022",
+ title: new LocalizableResourceString(nameof(SR.MalformedFormatStringsMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.MalformedFormatStringsMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor GeneratingForMax6Arguments { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1023",
+ title: new LocalizableResourceString(nameof(SR.GeneratingForMax6ArgumentsMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.GeneratingForMax6ArgumentsMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+ }
+}
--- /dev/null
+// 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.Text;
+using System.Threading;
+
+namespace Microsoft.Extensions.Logging.Generators
+{
+ public partial class LoggerMessageGenerator
+ {
+ internal class Emitter
+ {
+ // The maximum arity of LoggerMessage.Define.
+ private const int MaxLoggerMessageDefineArguments = 6;
+ private const int DefaultStringBuilderCapacity = 1024;
+
+ private readonly string _generatedCodeAttribute =
+ $"global::System.CodeDom.Compiler.GeneratedCodeAttribute(" +
+ $"\"{typeof(Emitter).Assembly.GetName().Name}\", " +
+ $"\"{typeof(Emitter).Assembly.GetName().Version}\")";
+ private readonly StringBuilder _builder = new StringBuilder(DefaultStringBuilderCapacity);
+
+ public string Emit(IReadOnlyList<LoggerClass> logClasses, CancellationToken cancellationToken)
+ {
+ _builder.Clear();
+ _builder.AppendLine("// <auto-generated/>");
+ _builder.AppendLine("#nullable enable");
+
+ foreach (LoggerClass lc in logClasses)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ GenType(lc);
+ }
+
+ return _builder.ToString();
+ }
+
+ private static bool UseLoggerMessageDefine(LoggerMethod lm)
+ {
+ bool result =
+ (lm.TemplateParameters.Count <= MaxLoggerMessageDefineArguments) && // more args than LoggerMessage.Define can handle
+ (lm.Level != null) && // dynamic log level, which LoggerMessage.Define can't handle
+ (lm.TemplateList.Count == lm.TemplateParameters.Count); // mismatch in template to args, which LoggerMessage.Define can't handle
+
+ if (result)
+ {
+ // make sure the order of the templates matches the order of the logging method parameter
+ int count = 0;
+ foreach (string t in lm.TemplateList)
+ {
+ if (!t.Equals(lm.TemplateParameters[count].Name, StringComparison.OrdinalIgnoreCase))
+ {
+ // order doesn't match, can't use LoggerMessage.Define
+ return false;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private void GenType(LoggerClass lc)
+ {
+ if (!string.IsNullOrWhiteSpace(lc.Namespace))
+ {
+ _builder.Append($@"
+namespace {lc.Namespace}
+{{");
+ }
+
+ _builder.Append($@"
+ partial class {lc.Name} {lc.Constraints}
+ {{");
+
+ foreach (LoggerMethod lm in lc.Methods)
+ {
+ if (!UseLoggerMessageDefine(lm))
+ {
+ GenStruct(lm);
+ }
+
+ GenLogMethod(lm);
+ }
+
+ GenEnumerationHelper(lc);
+
+ _builder.Append($@"
+ }}");
+
+ if (!string.IsNullOrWhiteSpace(lc.Namespace))
+ {
+ _builder.Append($@"
+}}");
+ }
+ }
+
+ private void GenStruct(LoggerMethod lm)
+ {
+ _builder.AppendLine($@"
+ [{_generatedCodeAttribute}]
+ private readonly struct __{lm.Name}Struct : global::System.Collections.Generic.IReadOnlyList<global::System.Collections.Generic.KeyValuePair<string, object?>>
+ {{");
+ GenFields(lm);
+
+ if (lm.TemplateParameters.Count > 0)
+ {
+ _builder.Append($@"
+ public __{lm.Name}Struct(");
+ GenArguments(lm);
+ _builder.Append($@")
+ {{");
+ _builder.AppendLine();
+ GenFieldAssignments(lm);
+ _builder.Append($@"
+ }}
+");
+ }
+
+ _builder.Append($@"
+ public override string ToString()
+ {{
+");
+ GenVariableAssignments(lm);
+ _builder.Append($@"
+ return $""{lm.Message}"";
+ }}
+");
+ _builder.Append($@"
+ public static string Format(__{lm.Name}Struct state, global::System.Exception? ex) => state.ToString();
+
+ public int Count => {lm.TemplateParameters.Count + 1};
+
+ public global::System.Collections.Generic.KeyValuePair<string, object?> this[int index]
+ {{
+ get => index switch
+ {{
+");
+ GenCases(lm);
+ _builder.Append($@"
+ _ => throw new global::System.IndexOutOfRangeException(nameof(index)), // return the same exception LoggerMessage.Define returns in this case
+ }};
+ }}
+
+ public global::System.Collections.Generic.IEnumerator<global::System.Collections.Generic.KeyValuePair<string, object?>> GetEnumerator()
+ {{
+ for (int i = 0; i < {lm.TemplateParameters.Count + 1}; i++)
+ {{
+ yield return this[i];
+ }}
+ }}
+
+ global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
+ }}
+");
+ }
+
+ private void GenFields(LoggerMethod lm)
+ {
+ foreach (LoggerParameter p in lm.TemplateParameters)
+ {
+ _builder.AppendLine($" private readonly {p.Type} _{p.Name};");
+ }
+ }
+
+ private void GenFieldAssignments(LoggerMethod lm)
+ {
+ foreach (LoggerParameter p in lm.TemplateParameters)
+ {
+ _builder.AppendLine($" this._{p.Name} = {p.Name};");
+ }
+ }
+
+ private void GenVariableAssignments(LoggerMethod lm)
+ {
+ foreach (KeyValuePair<string, string> t in lm.TemplateMap)
+ {
+ int index = 0;
+ foreach (LoggerParameter p in lm.TemplateParameters)
+ {
+ if (t.Key.Equals(p.Name, System.StringComparison.OrdinalIgnoreCase))
+ {
+ break;
+ }
+
+ index++;
+ }
+
+ // check for an index that's too big, this can happen in some cases of malformed input
+ if (index < lm.TemplateParameters.Count)
+ {
+ if (lm.TemplateParameters[index].IsEnumerable)
+ {
+ _builder.AppendLine($" var {t.Key} = "
+ + $"__Enumerate((global::System.Collections.IEnumerable ?)this._{lm.TemplateParameters[index].Name});");
+ }
+ else
+ {
+ _builder.AppendLine($" var {t.Key} = this._{lm.TemplateParameters[index].Name};");
+ }
+ }
+ }
+ }
+
+ private void GenCases(LoggerMethod lm)
+ {
+ int index = 0;
+ foreach (LoggerParameter p in lm.TemplateParameters)
+ {
+ string name = p.Name;
+ if (lm.TemplateMap.ContainsKey(name))
+ {
+ // take the letter casing from the template
+ name = lm.TemplateMap[name];
+ }
+
+ _builder.AppendLine($" {index++} => new global::System.Collections.Generic.KeyValuePair<string, object?>(\"{name}\", this._{p.Name}),");
+ }
+
+ _builder.AppendLine($" {index++} => new global::System.Collections.Generic.KeyValuePair<string, object?>(\"{{OriginalFormat}}\", \"{ConvertEndOfLineAndQuotationCharactersToEscapeForm(lm.Message)}\"),");
+ }
+
+ private void GenCallbackArguments(LoggerMethod lm)
+ {
+ foreach (LoggerParameter p in lm.TemplateParameters)
+ {
+ _builder.Append($"{p.Name}, ");
+ }
+ }
+
+ private void GenDefineTypes(LoggerMethod lm, bool brackets)
+ {
+ if (lm.TemplateParameters.Count == 0)
+ {
+ return;
+ }
+ if (brackets)
+ {
+ _builder.Append("<");
+ }
+
+ bool firstItem = true;
+ foreach (LoggerParameter p in lm.TemplateParameters)
+ {
+ if (firstItem)
+ {
+ firstItem = false;
+ }
+ else
+ {
+ _builder.Append(", ");
+ }
+
+ _builder.Append($"{p.Type}");
+ }
+
+ if (brackets)
+ {
+ _builder.Append(">");
+ }
+ else
+ {
+ _builder.Append(", ");
+ }
+ }
+
+ private void GenParameters(LoggerMethod lm)
+ {
+ bool firstItem = true;
+ foreach (LoggerParameter p in lm.AllParameters)
+ {
+ if (firstItem)
+ {
+ firstItem = false;
+ }
+ else
+ {
+ _builder.Append(", ");
+ }
+
+ _builder.Append($"{p.Type} {p.Name}");
+ }
+ }
+
+ private void GenArguments(LoggerMethod lm)
+ {
+ bool firstItem = true;
+ foreach (LoggerParameter p in lm.TemplateParameters)
+ {
+ if (firstItem)
+ {
+ firstItem = false;
+ }
+ else
+ {
+ _builder.Append(", ");
+ }
+
+ _builder.Append($"{p.Type} {p.Name}");
+ }
+ }
+
+ private void GenHolder(LoggerMethod lm)
+ {
+ string typeName = $"__{lm.Name}Struct";
+
+ _builder.Append($"new {typeName}(");
+ foreach (LoggerParameter p in lm.TemplateParameters)
+ {
+ if (p != lm.TemplateParameters[0])
+ {
+ _builder.Append(", ");
+ }
+
+ _builder.Append(p.Name);
+ }
+
+ _builder.Append(')');
+ }
+
+ private void GenLogMethod(LoggerMethod lm)
+ {
+ string level = GetLogLevel(lm);
+ string extension = (lm.IsExtensionMethod ? "this " : string.Empty);
+ string eventName = string.IsNullOrWhiteSpace(lm.EventName) ? $"nameof({lm.Name})" : $"\"{lm.EventName}\"";
+ string exceptionArg = GetException(lm);
+ string logger = GetLogger(lm);
+
+ if (UseLoggerMessageDefine(lm))
+ {
+ _builder.Append($@"
+ [{_generatedCodeAttribute}]
+ private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, ");
+
+ GenDefineTypes(lm, brackets: false);
+
+ _builder.Append(@$"global::System.Exception?> __{lm.Name}Callback =
+ global::Microsoft.Extensions.Logging.LoggerMessage.Define");
+
+ GenDefineTypes(lm, brackets: true);
+
+ _builder.Append(@$"({level}, new global::Microsoft.Extensions.Logging.EventId({lm.EventId}, {eventName}), ""{ConvertEndOfLineAndQuotationCharactersToEscapeForm(lm.Message)}"", true);
+");
+ }
+
+ _builder.Append($@"
+ [{_generatedCodeAttribute}]
+ {lm.Modifiers} void {lm.Name}({extension}");
+
+ GenParameters(lm);
+
+ _builder.Append($@")
+ {{
+ if ({logger}.IsEnabled({level}))
+ {{");
+
+ if (UseLoggerMessageDefine(lm))
+ {
+ _builder.Append($@"
+ __{lm.Name}Callback({logger}, ");
+
+ GenCallbackArguments(lm);
+
+ _builder.Append(@$"{exceptionArg});");
+ }
+ else
+ {
+ _builder.Append($@"
+ {logger}.Log(
+ {level},
+ new global::Microsoft.Extensions.Logging.EventId({lm.EventId}, {eventName}),
+ ");
+ GenHolder(lm);
+ _builder.Append($@",
+ {exceptionArg},
+ __{lm.Name}Struct.Format);");
+ }
+
+ _builder.Append($@"
+ }}
+ }}");
+
+ static string GetException(LoggerMethod lm)
+ {
+ string exceptionArg = "null";
+ foreach (LoggerParameter p in lm.AllParameters)
+ {
+ if (p.IsException)
+ {
+ exceptionArg = p.Name;
+ break;
+ }
+ }
+ return exceptionArg;
+ }
+
+ static string GetLogger(LoggerMethod lm)
+ {
+ string logger = lm.LoggerField;
+ foreach (LoggerParameter p in lm.AllParameters)
+ {
+ if (p.IsLogger)
+ {
+ logger = p.Name;
+ break;
+ }
+ }
+ return logger;
+ }
+
+ static string GetLogLevel(LoggerMethod lm)
+ {
+ string level = string.Empty;
+
+ if (lm.Level == null)
+ {
+ foreach (LoggerParameter p in lm.AllParameters)
+ {
+ if (p.IsLogLevel)
+ {
+ level = p.Name;
+ break;
+ }
+ }
+ }
+ else
+ {
+ level = lm.Level switch
+ {
+ 0 => "global::Microsoft.Extensions.Logging.LogLevel.Trace",
+ 1 => "global::Microsoft.Extensions.Logging.LogLevel.Debug",
+ 2 => "global::Microsoft.Extensions.Logging.LogLevel.Information",
+ 3 => "global::Microsoft.Extensions.Logging.LogLevel.Warning",
+ 4 => "global::Microsoft.Extensions.Logging.LogLevel.Error",
+ 5 => "global::Microsoft.Extensions.Logging.LogLevel.Critical",
+ 6 => "global::Microsoft.Extensions.Logging.LogLevel.None",
+ _ => $"(global::Microsoft.Extensions.Logging.LogLevel){lm.Level}",
+ };
+ }
+
+ return level;
+ }
+ }
+
+ private void GenEnumerationHelper(LoggerClass lc)
+ {
+ foreach (LoggerMethod lm in lc.Methods)
+ {
+ if (UseLoggerMessageDefine(lm))
+ {
+ foreach (LoggerParameter p in lm.TemplateParameters)
+ {
+ if (p.IsEnumerable)
+ {
+ _builder.Append($@"
+ [{_generatedCodeAttribute}]
+ private static string __Enumerate(global::System.Collections.IEnumerable? enumerable)
+ {{
+ if (enumerable == null)
+ {{
+ return ""(null)"";
+ }}
+
+ var sb = new global::System.Text.StringBuilder();
+ _ = sb.Append('[');
+
+ bool first = true;
+ foreach (object e in enumerable)
+ {{
+ if (!first)
+ {{
+ _ = sb.Append("", "");
+ }}
+
+ if (e == null)
+ {{
+ _ = sb.Append(""(null)"");
+ }}
+ else
+ {{
+ if (e is global::System.IFormattable fmt)
+ {{
+ _ = sb.Append(fmt.ToString(null, global::System.Globalization.CultureInfo.InvariantCulture));
+ }}
+ else
+ {{
+ _ = sb.Append(e);
+ }}
+ }}
+
+ first = false;
+ }}
+
+ _ = sb.Append(']');
+
+ return sb.ToString();
+ }}
+");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static string ConvertEndOfLineAndQuotationCharactersToEscapeForm(string s)
+ {
+ int index = 0;
+ while (index < s.Length)
+ {
+ if (s[index] == '\n' || s[index] == '\r' || s[index] == '"')
+ {
+ break;
+ }
+ index++;
+ }
+
+ if (index >= s.Length)
+ {
+ return s;
+ }
+
+ StringBuilder sb = new StringBuilder(s.Length);
+ sb.Append(s, 0, index);
+
+ while (index < s.Length)
+ {
+ switch (s[index])
+ {
+ case '\n':
+ sb.Append('\\');
+ sb.Append('n');
+ break;
+
+ case '\r':
+ sb.Append('\\');
+ sb.Append('r');
+ break;
+
+ case '"':
+ sb.Append('\\');
+ sb.Append('"');
+ break;
+
+ default:
+ sb.Append(s[index]);
+ break;
+ }
+
+ index++;
+ }
+
+ return sb.ToString();
+ }
+ }
+}
--- /dev/null
+// 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.Threading;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Microsoft.Extensions.Logging.Generators
+{
+ public partial class LoggerMessageGenerator
+ {
+ internal class Parser
+ {
+ private readonly CancellationToken _cancellationToken;
+ private readonly Compilation _compilation;
+ private readonly Action<Diagnostic> _reportDiagnostic;
+
+ public Parser(Compilation compilation, Action<Diagnostic> reportDiagnostic, CancellationToken cancellationToken)
+ {
+ _compilation = compilation;
+ _cancellationToken = cancellationToken;
+ _reportDiagnostic = reportDiagnostic;
+ }
+
+ /// <summary>
+ /// Gets the set of logging classes containing methods to output.
+ /// </summary>
+ public IReadOnlyList<LoggerClass> GetLogClasses(IEnumerable<ClassDeclarationSyntax> classes)
+ {
+ const string LoggerMessageAttribute = "Microsoft.Extensions.Logging.LoggerMessageAttribute";
+
+ INamedTypeSymbol loggerMessageAttribute = _compilation.GetTypeByMetadataName(LoggerMessageAttribute);
+ if (loggerMessageAttribute == null)
+ {
+ // nothing to do if this type isn't available
+ return Array.Empty<LoggerClass>();
+ }
+
+ INamedTypeSymbol loggerSymbol = _compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.ILogger");
+ if (loggerSymbol == null)
+ {
+ // nothing to do if this type isn't available
+ return Array.Empty<LoggerClass>();
+ }
+
+ INamedTypeSymbol logLevelSymbol = _compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.LogLevel");
+ if (logLevelSymbol == null)
+ {
+ // nothing to do if this type isn't available
+ return Array.Empty<LoggerClass>();
+ }
+
+ INamedTypeSymbol exceptionSymbol = _compilation.GetTypeByMetadataName("System.Exception");
+ if (exceptionSymbol == null)
+ {
+ Diag(DiagnosticDescriptors.MissingRequiredType, null, "System.Exception");
+ return Array.Empty<LoggerClass>();
+ }
+
+ INamedTypeSymbol enumerableSymbol = _compilation.GetTypeByMetadataName("System.Collections.IEnumerable");
+ if (enumerableSymbol == null)
+ {
+ Diag(DiagnosticDescriptors.MissingRequiredType, null, "System.Collections.IEnumerable");
+ return Array.Empty<LoggerClass>();
+ }
+
+ INamedTypeSymbol stringSymbol = _compilation.GetTypeByMetadataName("System.String");
+ if (stringSymbol == null)
+ {
+ Diag(DiagnosticDescriptors.MissingRequiredType, null, "System.String");
+ return Array.Empty<LoggerClass>();
+ }
+
+ var results = new List<LoggerClass>();
+ var ids = new HashSet<int>();
+
+ // we enumerate by syntax tree, to minimize the need to instantiate semantic models (since they're expensive)
+ foreach (var group in classes.GroupBy(x => x.SyntaxTree))
+ {
+ SemanticModel? sm = null;
+ foreach (ClassDeclarationSyntax classDec in group)
+ {
+ // stop if we're asked to
+ _cancellationToken.ThrowIfCancellationRequested();
+
+ LoggerClass? lc = null;
+ string nspace = string.Empty;
+ string? loggerField = null;
+ bool multipleLoggerFields = false;
+
+ ids.Clear();
+ foreach (var member in classDec.Members)
+ {
+ var method = member as MethodDeclarationSyntax;
+ if (method == null)
+ {
+ // we only care about methods
+ continue;
+ }
+
+ foreach (AttributeListSyntax mal in method.AttributeLists)
+ {
+ foreach (AttributeSyntax ma in mal.Attributes)
+ {
+ sm ??= _compilation.GetSemanticModel(classDec.SyntaxTree);
+
+ IMethodSymbol attrCtorSymbol = sm.GetSymbolInfo(ma, _cancellationToken).Symbol as IMethodSymbol;
+ if (attrCtorSymbol == null || !loggerMessageAttribute.Equals(attrCtorSymbol.ContainingType, SymbolEqualityComparer.Default))
+ {
+ // badly formed attribute definition, or not the right attribute
+ continue;
+ }
+
+ (int eventId, int? level, string? message, string? eventName) = ExtractAttributeValues(ma.ArgumentList!, sm);
+
+ IMethodSymbol? methodSymbol = sm.GetDeclaredSymbol(method, _cancellationToken);
+ if (methodSymbol != null)
+ {
+ var lm = new LoggerMethod
+ {
+ Name = method.Identifier.ToString(),
+ Level = level,
+ Message = message ?? string.Empty,
+ EventId = eventId,
+ EventName = eventName,
+ IsExtensionMethod = methodSymbol.IsExtensionMethod,
+ Modifiers = method.Modifiers.ToString(),
+ };
+
+ ExtractTemplates(message, lm.TemplateMap, lm.TemplateList);
+
+ bool keepMethod = true; // whether or not we want to keep the method definition or if it's got errors making it so we should discard it instead
+ if (lm.Name[0] == '_')
+ {
+ // can't have logging method names that start with _ since that can lead to conflicting symbol names
+ // because the generated symbols start with _
+ Diag(DiagnosticDescriptors.InvalidLoggingMethodName, method.Identifier.GetLocation());
+ keepMethod = false;
+ }
+
+ if (sm.GetTypeInfo(method.ReturnType!).Type!.SpecialType != SpecialType.System_Void)
+ {
+ // logging methods must return void
+ Diag(DiagnosticDescriptors.LoggingMethodMustReturnVoid, method.ReturnType.GetLocation());
+ keepMethod = false;
+ }
+
+ if (method.Arity > 0)
+ {
+ // we don't currently support generic methods
+ Diag(DiagnosticDescriptors.LoggingMethodIsGeneric, method.Identifier.GetLocation());
+ keepMethod = false;
+ }
+
+ bool isStatic = false;
+ bool isPartial = false;
+ foreach (SyntaxToken mod in method.Modifiers)
+ {
+ switch (mod.Text)
+ {
+ case "partial":
+ isPartial = true;
+ break;
+
+ case "static":
+ isStatic = true;
+ break;
+ }
+ }
+
+ if (!isPartial)
+ {
+ Diag(DiagnosticDescriptors.LoggingMethodMustBePartial, method.GetLocation());
+ keepMethod = false;
+ }
+
+ if (method.Body != null)
+ {
+ Diag(DiagnosticDescriptors.LoggingMethodHasBody, method.Body.GetLocation());
+ keepMethod = false;
+ }
+
+ // ensure there are no duplicate ids.
+ if (ids.Contains(lm.EventId))
+ {
+ Diag(DiagnosticDescriptors.ShouldntReuseEventIds, ma.GetLocation(), lm.EventId, classDec.Identifier.Text);
+ }
+ else
+ {
+ _ = ids.Add(lm.EventId);
+ }
+
+ string msg = lm.Message;
+ if (msg.StartsWith("INFORMATION:", StringComparison.OrdinalIgnoreCase)
+ || msg.StartsWith("INFO:", StringComparison.OrdinalIgnoreCase)
+ || msg.StartsWith("WARNING:", StringComparison.OrdinalIgnoreCase)
+ || msg.StartsWith("WARN:", StringComparison.OrdinalIgnoreCase)
+ || msg.StartsWith("ERROR:", StringComparison.OrdinalIgnoreCase)
+ || msg.StartsWith("ERR:", StringComparison.OrdinalIgnoreCase))
+ {
+ Diag(DiagnosticDescriptors.RedundantQualifierInMessage, ma.GetLocation(), method.Identifier.ToString());
+ }
+
+ bool foundLogger = false;
+ bool foundException = false;
+ bool foundLogLevel = level != null;
+ foreach (ParameterSyntax p in method.ParameterList.Parameters)
+ {
+ string paramName = p.Identifier.ToString();
+ if (string.IsNullOrWhiteSpace(paramName))
+ {
+ // semantic problem, just bail quietly
+ keepMethod = false;
+ break;
+ }
+
+ IParameterSymbol? declSymbol = sm.GetDeclaredSymbol(p);
+ ITypeSymbol paramSymbol = declSymbol!.Type;
+ if (paramSymbol is IErrorTypeSymbol)
+ {
+ // semantic problem, just bail quietly
+ keepMethod = false;
+ break;
+ }
+
+ IParameterSymbol declaredType = sm.GetDeclaredSymbol(p);
+ string typeName = declaredType!.Type.ToDisplayString(
+ SymbolDisplayFormat.FullyQualifiedFormat.WithMiscellaneousOptions(
+ SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier));
+
+ var lp = new LoggerParameter
+ {
+ Name = paramName,
+ Type = typeName,
+ IsLogger = !foundLogger && IsBaseOrIdentity(paramSymbol!, loggerSymbol),
+ IsException = !foundException && IsBaseOrIdentity(paramSymbol!, exceptionSymbol),
+ IsLogLevel = !foundLogLevel && IsBaseOrIdentity(paramSymbol!, logLevelSymbol),
+ IsEnumerable = IsBaseOrIdentity(paramSymbol!, enumerableSymbol) && !IsBaseOrIdentity(paramSymbol!, stringSymbol),
+ };
+
+ foundLogger |= lp.IsLogger;
+ foundException |= lp.IsException;
+ foundLogLevel |= lp.IsLogLevel;
+
+ if (lp.IsLogger && lm.TemplateMap.ContainsKey(paramName))
+ {
+ Diag(DiagnosticDescriptors.ShouldntMentionLoggerInMessage, p.Identifier.GetLocation(), paramName);
+ }
+ else if (lp.IsException && lm.TemplateMap.ContainsKey(paramName))
+ {
+ Diag(DiagnosticDescriptors.ShouldntMentionExceptionInMessage, p.Identifier.GetLocation(), paramName);
+ }
+ else if (lp.IsLogLevel && lm.TemplateMap.ContainsKey(paramName))
+ {
+ Diag(DiagnosticDescriptors.ShouldntMentionLogLevelInMessage, p.Identifier.GetLocation(), paramName);
+ }
+ else if (lp.IsLogLevel && level != null && !lm.TemplateMap.ContainsKey(paramName))
+ {
+ Diag(DiagnosticDescriptors.ArgumentHasNoCorrespondingTemplate, p.Identifier.GetLocation(), paramName);
+ }
+ else if (lp.IsTemplateParameter && !lm.TemplateMap.ContainsKey(paramName))
+ {
+ Diag(DiagnosticDescriptors.ArgumentHasNoCorrespondingTemplate, p.Identifier.GetLocation(), paramName);
+ }
+
+ if (paramName[0] == '_')
+ {
+ // can't have logging method parameter names that start with _ since that can lead to conflicting symbol names
+ // because all generated symbols start with _
+ Diag(DiagnosticDescriptors.InvalidLoggingMethodParameterName, p.Identifier.GetLocation());
+ }
+
+ lm.AllParameters.Add(lp);
+ if (lp.IsTemplateParameter)
+ {
+ lm.TemplateParameters.Add(lp);
+ }
+ }
+
+ if (keepMethod)
+ {
+ if (isStatic && !foundLogger)
+ {
+ Diag(DiagnosticDescriptors.MissingLoggerArgument, method.GetLocation());
+ keepMethod = false;
+ }
+ else if (!isStatic && foundLogger)
+ {
+ Diag(DiagnosticDescriptors.LoggingMethodShouldBeStatic, method.GetLocation());
+ }
+ else if (!isStatic && !foundLogger)
+ {
+ if (loggerField == null)
+ {
+ (loggerField, multipleLoggerFields) = FindLoggerField(sm, classDec, loggerSymbol);
+ }
+
+ if (multipleLoggerFields)
+ {
+ Diag(DiagnosticDescriptors.MultipleLoggerFields, method.GetLocation(), classDec.Identifier.Text);
+ keepMethod = false;
+ }
+ else if (loggerField == null)
+ {
+ Diag(DiagnosticDescriptors.MissingLoggerField, method.GetLocation(), classDec.Identifier.Text);
+ keepMethod = false;
+ }
+ else
+ {
+ lm.LoggerField = loggerField;
+ }
+ }
+
+ if (level == null && !foundLogLevel)
+ {
+ Diag(DiagnosticDescriptors.MissingLogLevel, method.GetLocation());
+ keepMethod = false;
+ }
+
+ foreach (KeyValuePair<string, string> t in lm.TemplateMap)
+ {
+ bool found = false;
+ foreach (LoggerParameter p in lm.AllParameters)
+ {
+ if (t.Key.Equals(p.Name, StringComparison.OrdinalIgnoreCase))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ Diag(DiagnosticDescriptors.TemplateHasNoCorrespondingArgument, ma.GetLocation(), t);
+ }
+ }
+ }
+
+ if (lc == null)
+ {
+ // determine the namespace the class is declared in, if any
+ var ns = classDec.Parent as NamespaceDeclarationSyntax;
+ if (ns == null)
+ {
+ if (classDec.Parent is not CompilationUnitSyntax)
+ {
+ // since this generator doesn't know how to generate a nested type...
+ Diag(DiagnosticDescriptors.LoggingMethodInNestedType, classDec.Identifier.GetLocation());
+ keepMethod = false;
+ }
+ }
+ else
+ {
+ nspace = ns.Name.ToString();
+ while (true)
+ {
+ ns = ns.Parent as NamespaceDeclarationSyntax;
+ if (ns == null)
+ {
+ break;
+ }
+
+ nspace = $"{ns.Name}.{nspace}";
+ }
+ }
+ }
+
+ if (keepMethod)
+ {
+ lc ??= new LoggerClass
+ {
+ Namespace = nspace,
+ Name = classDec.Identifier.ToString() + classDec.TypeParameterList,
+ Constraints = classDec.ConstraintClauses.ToString(),
+ };
+
+ lc.Methods.Add(lm);
+ }
+ }
+ }
+ }
+ }
+
+ if (lc != null)
+ {
+ results.Add(lc);
+ }
+ }
+ }
+
+ return results;
+ }
+
+ private (string? loggerField, bool multipleLoggerFields) FindLoggerField(SemanticModel sm, TypeDeclarationSyntax classDec, ITypeSymbol loggerSymbol)
+ {
+ string? loggerField = null;
+
+ foreach (MemberDeclarationSyntax m in classDec.Members)
+ {
+ if (m is FieldDeclarationSyntax fds)
+ {
+ foreach (VariableDeclaratorSyntax v in fds.Declaration.Variables)
+ {
+ var fs = sm.GetDeclaredSymbol(v, _cancellationToken) as IFieldSymbol;
+ if (fs != null)
+ {
+ if (IsBaseOrIdentity(fs.Type, loggerSymbol))
+ {
+ if (loggerField == null)
+ {
+ loggerField = v.Identifier.Text;
+ }
+ else
+ {
+ return (null, true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return (loggerField, false);
+ }
+
+ private (int eventId, int? level, string? message, string? eventName) ExtractAttributeValues(AttributeArgumentListSyntax args, SemanticModel sm)
+ {
+ // two constructor arg shapes:
+ //
+ // (eventId, level, message)
+ // (eventId, message)
+
+ int eventId = 0;
+ int? level = null;
+ string? eventName = null;
+ string? message = null;
+ int numPositional = 0;
+ foreach (AttributeArgumentSyntax a in args.Arguments)
+ {
+ if (a.NameEquals != null)
+ {
+ switch (a.NameEquals.Name.ToString())
+ {
+ case "EventId":
+ eventId = (int)sm.GetConstantValue(a.Expression, _cancellationToken).Value!;
+ break;
+ case "EventName":
+ eventName = sm.GetConstantValue(a.Expression, _cancellationToken).ToString();
+ break;
+ case "Level":
+ level = (int)sm.GetConstantValue(a.Expression, _cancellationToken).Value!;
+ break;
+ case "Message":
+ message = sm.GetConstantValue(a.Expression, _cancellationToken).ToString();
+ break;
+ }
+ }
+ else if (a.NameColon != null)
+ {
+ switch (a.NameColon.Name.ToString())
+ {
+ case "eventId":
+ eventId = (int)sm.GetConstantValue(a.Expression, _cancellationToken).Value!;
+ break;
+
+ case "level":
+ level = (int)sm.GetConstantValue(a.Expression, _cancellationToken).Value!;
+ break;
+
+ case "message":
+ message = sm.GetConstantValue(a.Expression, _cancellationToken).ToString();
+ break;
+ }
+ }
+ else
+ {
+ switch (numPositional)
+ {
+ // event id
+ case 0:
+ eventId = (int)sm.GetConstantValue(a.Expression, _cancellationToken).Value!;
+ break;
+
+ // log level or message
+ case 1:
+ object o = sm.GetConstantValue(a.Expression, _cancellationToken).Value!;
+ if (o is int l)
+ {
+ level = l;
+ }
+ else
+ {
+ message = sm.GetConstantValue(a.Expression, _cancellationToken).ToString();
+ }
+
+ break;
+
+ // message
+ case 2:
+ message = sm.GetConstantValue(a.Expression, _cancellationToken).ToString();
+ break;
+ }
+
+ numPositional++;
+ }
+ }
+
+ return (eventId, level, message, eventName);
+ }
+
+ private void Diag(DiagnosticDescriptor desc, Location? location, params object?[]? messageArgs)
+ {
+ _reportDiagnostic(Diagnostic.Create(desc, location, messageArgs));
+ }
+
+ private bool IsBaseOrIdentity(ITypeSymbol source, ITypeSymbol dest)
+ {
+ Conversion conversion = _compilation.ClassifyConversion(source, dest);
+ return conversion.IsIdentity || (conversion.IsReference && conversion.IsImplicit);
+ }
+
+ private static readonly char[] _formatDelimiters = { ',', ':' };
+
+ /// <summary>
+ /// Finds the template arguments contained in the message string.
+ /// </summary>
+ private static void ExtractTemplates(string? message, IDictionary<string, string> templateMap, IList<string> templateList)
+ {
+ if (string.IsNullOrEmpty(message))
+ {
+ return;
+ }
+
+ int scanIndex = 0;
+ int endIndex = message!.Length;
+
+ while (scanIndex < endIndex)
+ {
+ int openBraceIndex = FindBraceIndex(message, '{', scanIndex, endIndex);
+ int closeBraceIndex = FindBraceIndex(message, '}', openBraceIndex, endIndex);
+
+ if (closeBraceIndex == endIndex)
+ {
+ scanIndex = endIndex;
+ }
+ else
+ {
+ // Format item syntax : { index[,alignment][ :formatString] }.
+ int formatDelimiterIndex = FindIndexOfAny(message, _formatDelimiters, openBraceIndex, closeBraceIndex);
+
+ string templateName = message.Substring(openBraceIndex + 1, formatDelimiterIndex - openBraceIndex - 1);
+ templateMap[templateName] = templateName;
+ templateList.Add(templateName);
+ scanIndex = closeBraceIndex + 1;
+ }
+ }
+ }
+
+ private static int FindBraceIndex(string message, char brace, int startIndex, int endIndex)
+ {
+ // Example: {{prefix{{{Argument}}}suffix}}.
+ int braceIndex = endIndex;
+ int scanIndex = startIndex;
+ int braceOccurrenceCount = 0;
+
+ while (scanIndex < endIndex)
+ {
+ if (braceOccurrenceCount > 0 && message[scanIndex] != brace)
+ {
+ if (braceOccurrenceCount % 2 == 0)
+ {
+ // Even number of '{' or '}' found. Proceed search with next occurrence of '{' or '}'.
+ braceOccurrenceCount = 0;
+ braceIndex = endIndex;
+ }
+ else
+ {
+ // An unescaped '{' or '}' found.
+ break;
+ }
+ }
+ else if (message[scanIndex] == brace)
+ {
+ if (brace == '}')
+ {
+ if (braceOccurrenceCount == 0)
+ {
+ // For '}' pick the first occurrence.
+ braceIndex = scanIndex;
+ }
+ }
+ else
+ {
+ // For '{' pick the last occurrence.
+ braceIndex = scanIndex;
+ }
+
+ braceOccurrenceCount++;
+ }
+
+ scanIndex++;
+ }
+
+ return braceIndex;
+ }
+
+ private static int FindIndexOfAny(string message, char[] chars, int startIndex, int endIndex)
+ {
+ int findIndex = message.IndexOfAny(chars, startIndex, endIndex - startIndex);
+ return findIndex == -1 ? endIndex : findIndex;
+ }
+ }
+
+ /// <summary>
+ /// A logger class holding a bunch of logger methods.
+ /// </summary>
+ internal class LoggerClass
+ {
+ public readonly List<LoggerMethod> Methods = new ();
+ public string Namespace = string.Empty;
+ public string Name = string.Empty;
+ public string Constraints = string.Empty;
+ }
+
+ /// <summary>
+ /// A logger method in a logger class.
+ /// </summary>
+ internal class LoggerMethod
+ {
+ public readonly List<LoggerParameter> AllParameters = new ();
+ public readonly List<LoggerParameter> TemplateParameters = new ();
+ public readonly Dictionary<string, string> TemplateMap = new (StringComparer.OrdinalIgnoreCase);
+ public readonly List<string> TemplateList = new ();
+ public string Name = string.Empty;
+ public string Message = string.Empty;
+ public int? Level;
+ public int EventId;
+ public string? EventName;
+ public bool IsExtensionMethod;
+ public string Modifiers = string.Empty;
+ public string LoggerField;
+ }
+
+ /// <summary>
+ /// A single parameter to a logger method.
+ /// </summary>
+ internal class LoggerParameter
+ {
+ public string Name = string.Empty;
+ public string Type = string.Empty;
+ public bool IsLogger;
+ public bool IsException;
+ public bool IsLogLevel;
+ public bool IsEnumerable;
+ // A parameter flagged as IsTemplateParameter is not going to be taken care of specially as an argument to ILogger.Log
+ // but instead is supposed to be taken as a parameter for the template.
+ public bool IsTemplateParameter => !IsLogger && !IsException && !IsLogLevel;
+ }
+ }
+}
--- /dev/null
+// 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.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Text;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Text;
+
+[assembly: System.Resources.NeutralResourcesLanguage("en-us")]
+
+namespace Microsoft.Extensions.Logging.Generators
+{
+ [Generator]
+ public partial class LoggerMessageGenerator : ISourceGenerator
+ {
+ [ExcludeFromCodeCoverage]
+ public void Initialize(GeneratorInitializationContext context)
+ {
+ context.RegisterForSyntaxNotifications(SyntaxReceiver.Create);
+ }
+
+ [ExcludeFromCodeCoverage]
+ public void Execute(GeneratorExecutionContext context)
+ {
+ if (context.SyntaxReceiver is not SyntaxReceiver receiver || receiver.ClassDeclarations.Count == 0)
+ {
+ // nothing to do yet
+ return;
+ }
+
+ var p = new Parser(context.Compilation, context.ReportDiagnostic, context.CancellationToken);
+ IReadOnlyList<LoggerClass> logClasses = p.GetLogClasses(receiver.ClassDeclarations);
+ if (logClasses.Count > 0)
+ {
+ var e = new Emitter();
+ string result = e.Emit(logClasses, context.CancellationToken);
+
+ context.AddSource(nameof(LoggerMessageGenerator), SourceText.From(result, Encoding.UTF8));
+ }
+ }
+
+ [ExcludeFromCodeCoverage]
+ private sealed class SyntaxReceiver : ISyntaxReceiver
+ {
+ internal static ISyntaxReceiver Create()
+ {
+ return new SyntaxReceiver();
+ }
+
+ public List<ClassDeclarationSyntax> ClassDeclarations { get; } = new ();
+
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
+ {
+ if (syntaxNode is ClassDeclarationSyntax classSyntax)
+ {
+ ClassDeclarations.Add(classSyntax);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFrameworks>netstandard2.0</TargetFrameworks>
+ <Nullable>enable</Nullable>
+ <EnableDefaultItems>true</EnableDefaultItems>
+ <EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
+ <UsingToolXliff>true</UsingToolXliff>
+ <CLSCompliant>false</CLSCompliant>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageDestination Include="analyzers\dotnet\cs" />
+ </ItemGroup>
+
+ <Target Name="IncludeSatteliteResourceInPackage" BeforeTargets="GetFilesToPackage" DependsOnTargets="SatelliteDllsProjectOutputGroup">
+ <ItemGroup>
+ <AdditionalFileToPackage Include="%(SatelliteDllsProjectOutputGroupOutput.FullPath)" SubFolder="/%(SatelliteDllsProjectOutputGroupOutput.Culture)" />
+ </ItemGroup>
+ </Target>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(MicrosoftCodeAnalysisCSharpWorkspacesVersion)" PrivateAssets="all" />
+ <PackageReference Include="Microsoft.DotNet.Build.Tasks.Packaging" Version="$(MicrosoftDotNetBuildTasksPackagingVersion)" PrivateAssets="all" />
+ </ItemGroup>
+
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="InvalidLoggingMethodNameMessage" xml:space="preserve">
+ <value>Logging method names cannot start with _</value>
+ </data>
+ <data name="InvalidLoggingMethodParameterNameMessage" xml:space="preserve">
+ <value>Logging method parameter names cannot start with _</value>
+ </data>
+ <data name="LoggingMethodInNestedTypeMessage" xml:space="preserve">
+ <value>Logging class cannot be in nested types</value>
+ </data>
+ <data name="MissingRequiredTypeTitle" xml:space="preserve">
+ <value>Could not find a required type definition</value>
+ </data>
+ <data name="MissingRequiredTypeMessage" xml:space="preserve">
+ <value>Could not find definition for type {0}</value>
+ </data>
+ <data name="ShouldntReuseEventIdsTitle" xml:space="preserve">
+ <value>Multiple logging methods cannot use the same event id within a class</value>
+ </data>
+ <data name="ShouldntReuseEventIdsMessage" xml:space="preserve">
+ <value>Multiple logging methods are using event id {0} in class {1}</value>
+ </data>
+ <data name="LoggingMethodMustReturnVoidMessage" xml:space="preserve">
+ <value>Logging methods must return void</value>
+ </data>
+ <data name="MissingLoggerArgumentMessage" xml:space="preserve">
+ <value>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</value>
+ <comment>{Locked="Microsoft.Extensions.Logging.ILogger"}</comment>
+ </data>
+ <data name="LoggingMethodShouldBeStaticMessage" xml:space="preserve">
+ <value>Logging methods must be static</value>
+ </data>
+ <data name="LoggingMethodMustBePartialMessage" xml:space="preserve">
+ <value>Logging methods must be partial</value>
+ </data>
+ <data name="LoggingMethodIsGenericMessage" xml:space="preserve">
+ <value>Logging methods cannot be generic</value>
+ </data>
+ <data name="ShouldntMentionInTemplateMessage" xml:space="preserve">
+ <value>Don't include a template for {0} in the logging message since it is implicitly taken care of</value>
+ </data>
+ <data name="ShouldntMentionExceptionInMessageTitle" xml:space="preserve">
+ <value>Don't include exception parameters as templates in the logging message</value>
+ </data>
+ <data name="RedundantQualifierInMessageMessage" xml:space="preserve">
+ <value>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</value>
+ </data>
+ <data name="RedundantQualifierInMessageTitle" xml:space="preserve">
+ <value>Redundant qualifier in logging message</value>
+ </data>
+ <data name="ArgumentHasNoCorrespondingTemplateMessage" xml:space="preserve">
+ <value>Argument {0} is not referenced from the logging message</value>
+ </data>
+ <data name="ArgumentHasNoCorrespondingTemplateTitle" xml:space="preserve">
+ <value>Argument is not referenced from the logging message</value>
+ </data>
+ <data name="TemplateHasNoCorrespondingArgumentMessage" xml:space="preserve">
+ <value>Template {0} is not provided as argument to the logging method</value>
+ </data>
+ <data name="TemplateHasNoCorrespondingArgumentTitle" xml:space="preserve">
+ <value>Logging template has no corresponding method argument</value>
+ </data>
+ <data name="LoggingMethodHasBodyMessage" xml:space="preserve">
+ <value>Logging methods cannot have a body</value>
+ </data>
+ <data name="MissingLogLevelMessage" xml:space="preserve">
+ <value>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</value>
+ </data>
+ <data name="ShouldntMentionLogLevelInMessageTitle" xml:space="preserve">
+ <value>Don't include log level parameters as templates in the logging message</value>
+ </data>
+ <data name="ShouldntMentionLoggerInMessageTitle" xml:space="preserve">
+ <value>Don't include logger parameters as templates in the logging message</value>
+ </data>
+ <data name="MissingLoggerFieldMessage" xml:space="preserve">
+ <value>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</value>
+ <comment>{Locked="Microsoft.Extensions.Logging.ILogger"}</comment>
+ </data>
+ <data name="MissingLoggerFieldTitle" xml:space="preserve">
+ <value>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</value>
+ <comment>{Locked="Microsoft.Extensions.Logging.ILogger"}</comment>
+ </data>
+ <data name="MultipleLoggerFieldsMessage" xml:space="preserve">
+ <value>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</value>
+ <comment>{Locked="Microsoft.Extensions.Logging.ILogger"}</comment>
+ </data>
+ <data name="MultipleLoggerFieldsTitle" xml:space="preserve">
+ <value>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</value>
+ <comment>{Locked="Microsoft.Extensions.Logging.ILogger"}</comment>
+ </data>
+ <data name="InconsistentTemplateCasingMessage" xml:space="preserve">
+ <value>Can't have the same template with different casing</value>
+ </data>
+ <data name="MalformedFormatStringsMessage" xml:space="preserve">
+ <value>Can't have malformed format strings (like dangling {, etc)</value>
+ </data>
+ <data name="GeneratingForMax6ArgumentsMessage" xml:space="preserve">
+ <value>Generating more than 6 arguments is not supported</value>
+ </data>
+</root>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="cs" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="de" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="es" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="fr" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="it" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="ja" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="ko" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="pl" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="pt-BR" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="ru" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="tr" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="zh-Hans" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="zh-Hant" original="../Strings.resx">
+ <body>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
+ <source>Argument {0} is not referenced from the logging message</source>
+ <target state="new">Argument {0} is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
+ <source>Argument is not referenced from the logging message</source>
+ <target state="new">Argument is not referenced from the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="GeneratingForMax6ArgumentsMessage">
+ <source>Generating more than 6 arguments is not supported</source>
+ <target state="new">Generating more than 6 arguments is not supported</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InconsistentTemplateCasingMessage">
+ <source>Can't have the same template with different casing</source>
+ <target state="new">Can't have the same template with different casing</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodNameMessage">
+ <source>Logging method names cannot start with _</source>
+ <target state="new">Logging method names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InvalidLoggingMethodParameterNameMessage">
+ <source>Logging method parameter names cannot start with _</source>
+ <target state="new">Logging method parameter names cannot start with _</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodHasBodyMessage">
+ <source>Logging methods cannot have a body</source>
+ <target state="new">Logging methods cannot have a body</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodInNestedTypeMessage">
+ <source>Logging class cannot be in nested types</source>
+ <target state="new">Logging class cannot be in nested types</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodIsGenericMessage">
+ <source>Logging methods cannot be generic</source>
+ <target state="new">Logging methods cannot be generic</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustBePartialMessage">
+ <source>Logging methods must be partial</source>
+ <target state="new">Logging methods must be partial</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodMustReturnVoidMessage">
+ <source>Logging methods must return void</source>
+ <target state="new">Logging methods must return void</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="LoggingMethodShouldBeStaticMessage">
+ <source>Logging methods must be static</source>
+ <target state="new">Logging methods must be static</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MalformedFormatStringsMessage">
+ <source>Can't have malformed format strings (like dangling {, etc)</source>
+ <target state="new">Can't have malformed format strings (like dangling {, etc)</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLogLevelMessage">
+ <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
+ <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingLoggerArgumentMessage">
+ <source>One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
+ <target state="new">One of the arguments to a logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldMessage">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingLoggerFieldTitle">
+ <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeMessage">
+ <source>Could not find definition for type {0}</source>
+ <target state="new">Could not find definition for type {0}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MissingRequiredTypeTitle">
+ <source>Could not find a required type definition</source>
+ <target state="new">Could not find a required type definition</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsMessage">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="MultipleLoggerFieldsTitle">
+ <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
+ <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
+ <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageMessage">
+ <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
+ <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="RedundantQualifierInMessageTitle">
+ <source>Redundant qualifier in logging message</source>
+ <target state="new">Redundant qualifier in logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionExceptionInMessageTitle">
+ <source>Don't include exception parameters as templates in the logging message</source>
+ <target state="new">Don't include exception parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionInTemplateMessage">
+ <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
+ <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
+ <source>Don't include log level parameters as templates in the logging message</source>
+ <target state="new">Don't include log level parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntMentionLoggerInMessageTitle">
+ <source>Don't include logger parameters as templates in the logging message</source>
+ <target state="new">Don't include logger parameters as templates in the logging message</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsMessage">
+ <source>Multiple logging methods are using event id {0} in class {1}</source>
+ <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ShouldntReuseEventIdsTitle">
+ <source>Multiple logging methods cannot use the same event id within a class</source>
+ <target state="new">Multiple logging methods cannot use the same event id within a class</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
+ <source>Template {0} is not provided as argument to the logging method</source>
+ <target state="new">Template {0} is not provided as argument to the logging method</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
+ <source>Logging template has no corresponding method argument</source>
+ <target state="new">Logging template has no corresponding method argument</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
<ProjectReference Include="..\src\Microsoft.Extensions.Logging.csproj">
<SupportedFramework>net461;netcoreapp2.0;uap10.0.16299;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
+ <ProjectReference Include="..\gen\Microsoft.Extensions.Logging.Generators.csproj" />
</ItemGroup>
<Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.targets))" />
</Project>
\ No newline at end of file
TraceState = 8,
TraceFlags = 16,
Tags = 32,
- Baggage = 64
+ Baggage = 64,
}
public static partial class FilterLoggingBuilderExtensions
{
public string ProviderName { get { throw null; } }
public override string ToString() { throw null; }
}
+ [System.AttributeUsageAttribute(System.AttributeTargets.Method)]
+ public sealed partial class LoggerMessageAttribute : System.Attribute
+ {
+ public LoggerMessageAttribute() { }
+ public int EventId { get { throw null; } set { } }
+ public string? EventName { get { throw null; } set { } }
+ public Microsoft.Extensions.Logging.LogLevel Level { get { throw null; } set { } }
+ public string Message { get { throw null; } set { } }
+ }
public static partial class LoggingBuilderExtensions
{
public static Microsoft.Extensions.Logging.ILoggingBuilder AddProvider(this Microsoft.Extensions.Logging.ILoggingBuilder builder, Microsoft.Extensions.Logging.ILoggerProvider provider) { throw null; }
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+namespace Microsoft.Extensions.Logging
+{
+ /// <summary>
+ /// Provides information to guide the production of a strongly-typed logging method.
+ /// </summary>
+ /// <remarks>
+ /// <para>The method this attribute is applied to:</para>
+ /// <para> - Must be a partial method.</para>
+ /// <para> - Must return <c>void</c>.</para>
+ /// <para> - Must not be generic.</para>
+ /// <para> - Must have an <see cref="ILogger"/> as one of its parameters.</para>
+ /// <para> - Must have a <see cref="Microsoft.Extensions.Logging.LogLevel"/> as one of its parameters.</para>
+ /// <para> - None of the parameters can be generic.</para>
+ /// </remarks>
+ /// <example>
+ /// <format type="text/markdown"><![CDATA[
+ /// ```csharp
+ /// static partial class Log
+ /// {
+ /// [LoggerMessage(EventId = 0, Message = "Could not open socket for {hostName}")]
+ /// static partial void CouldNotOpenSocket(ILogger logger, LogLevel level, string hostName);
+ /// }
+ /// ```
+ /// ]]></format>
+ /// </example>
+ [AttributeUsage(AttributeTargets.Method)]
+ public sealed class LoggerMessageAttribute : Attribute
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="LoggerMessageAttribute"/> class
+ /// which is used to guide the production of a strongly-typed logging method.
+ /// </summary>
+ public LoggerMessageAttribute() { }
+
+ /// <summary>
+ /// Gets the logging event id for the logging method.
+ /// </summary>
+ public int EventId { get; set; } = -1;
+
+ /// <summary>
+ /// Gets or sets the logging event name for the logging method.
+ /// </summary>
+ /// <remarks>
+ /// This will equal the method name if not specified.
+ /// </remarks>
+ public string? EventName { get; set; }
+
+ /// <summary>
+ /// Gets the logging level for the logging method.
+ /// </summary>
+ public LogLevel Level { get; set; } = LogLevel.None;
+
+ /// <summary>
+ /// Gets the message text for the logging method.
+ /// </summary>
+ public string Message { get; set; } = "";
+ }
+}
--- /dev/null
+// <auto-generated/>
+#nullable enable
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ partial class TestWithDynamicLogLevel
+ {
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
+ private readonly struct __M9Struct : global::System.Collections.Generic.IReadOnlyList<global::System.Collections.Generic.KeyValuePair<string, object?>>
+ {
+
+ public override string ToString()
+ {
+
+ return $"M9";
+ }
+
+ public static string Format(__M9Struct state, global::System.Exception? ex) => state.ToString();
+
+ public int Count => 1;
+
+ public global::System.Collections.Generic.KeyValuePair<string, object?> this[int index]
+ {
+ get => index switch
+ {
+ 0 => new global::System.Collections.Generic.KeyValuePair<string, object?>("{OriginalFormat}", "M9"),
+
+ _ => throw new global::System.IndexOutOfRangeException(nameof(index)), // return the same exception LoggerMessage.Define returns in this case
+ };
+ }
+
+ public global::System.Collections.Generic.IEnumerator<global::System.Collections.Generic.KeyValuePair<string, object?>> GetEnumerator()
+ {
+ for (int i = 0; i < 1; i++)
+ {
+ yield return this[i];
+ }
+ }
+
+ global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
+ }
+
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
+ public static partial void M9(global::Microsoft.Extensions.Logging.LogLevel level, global::Microsoft.Extensions.Logging.ILogger logger)
+ {
+ if (logger.IsEnabled(level))
+ {
+ logger.Log(
+ level,
+ new global::Microsoft.Extensions.Logging.EventId(9, nameof(M9)),
+ new __M9Struct(),
+ null,
+ __M9Struct.Format);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// <auto-generated/>
+#nullable enable
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ partial class TestWithMoreThan6Params
+ {
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
+ private readonly struct __Method9Struct : global::System.Collections.Generic.IReadOnlyList<global::System.Collections.Generic.KeyValuePair<string, object?>>
+ {
+ private readonly global::System.Int32 _p1;
+ private readonly global::System.Int32 _p2;
+ private readonly global::System.Int32 _p3;
+ private readonly global::System.Int32 _p4;
+ private readonly global::System.Int32 _p5;
+ private readonly global::System.Int32 _p6;
+ private readonly global::System.Int32 _p7;
+
+ public __Method9Struct(global::System.Int32 p1, global::System.Int32 p2, global::System.Int32 p3, global::System.Int32 p4, global::System.Int32 p5, global::System.Int32 p6, global::System.Int32 p7)
+ {
+ this._p1 = p1;
+ this._p2 = p2;
+ this._p3 = p3;
+ this._p4 = p4;
+ this._p5 = p5;
+ this._p6 = p6;
+ this._p7 = p7;
+
+ }
+
+ public override string ToString()
+ {
+ var p1 = this._p1;
+ var p2 = this._p2;
+ var p3 = this._p3;
+ var p4 = this._p4;
+ var p5 = this._p5;
+ var p6 = this._p6;
+ var p7 = this._p7;
+
+ return $"M9 {p1} {p2} {p3} {p4} {p5} {p6} {p7}";
+ }
+
+ public static string Format(__Method9Struct state, global::System.Exception? ex) => state.ToString();
+
+ public int Count => 8;
+
+ public global::System.Collections.Generic.KeyValuePair<string, object?> this[int index]
+ {
+ get => index switch
+ {
+ 0 => new global::System.Collections.Generic.KeyValuePair<string, object?>("p1", this._p1),
+ 1 => new global::System.Collections.Generic.KeyValuePair<string, object?>("p2", this._p2),
+ 2 => new global::System.Collections.Generic.KeyValuePair<string, object?>("p3", this._p3),
+ 3 => new global::System.Collections.Generic.KeyValuePair<string, object?>("p4", this._p4),
+ 4 => new global::System.Collections.Generic.KeyValuePair<string, object?>("p5", this._p5),
+ 5 => new global::System.Collections.Generic.KeyValuePair<string, object?>("p6", this._p6),
+ 6 => new global::System.Collections.Generic.KeyValuePair<string, object?>("p7", this._p7),
+ 7 => new global::System.Collections.Generic.KeyValuePair<string, object?>("{OriginalFormat}", "M9 {p1} {p2} {p3} {p4} {p5} {p6} {p7}"),
+
+ _ => throw new global::System.IndexOutOfRangeException(nameof(index)), // return the same exception LoggerMessage.Define returns in this case
+ };
+ }
+
+ public global::System.Collections.Generic.IEnumerator<global::System.Collections.Generic.KeyValuePair<string, object?>> GetEnumerator()
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ yield return this[i];
+ }
+ }
+
+ global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
+ }
+
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
+ public static partial void Method9(global::Microsoft.Extensions.Logging.ILogger logger, global::System.Int32 p1, global::System.Int32 p2, global::System.Int32 p3, global::System.Int32 p4, global::System.Int32 p5, global::System.Int32 p6, global::System.Int32 p7)
+ {
+ if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Error))
+ {
+ logger.Log(
+ global::Microsoft.Extensions.Logging.LogLevel.Error,
+ new global::Microsoft.Extensions.Logging.EventId(8, nameof(Method9)),
+ new __Method9Struct(p1, p2, p3, p4, p5, p6, p7),
+ null,
+ __Method9Struct.Format);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// <auto-generated/>
+#nullable enable
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ partial class TestWithOneParam
+ {
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
+ private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Int32, global::System.Exception?> __M0Callback =
+ global::Microsoft.Extensions.Logging.LoggerMessage.Define<global::System.Int32>(global::Microsoft.Extensions.Logging.LogLevel.Error, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0 {A1}", true);
+
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
+ public static partial void M0(global::Microsoft.Extensions.Logging.ILogger logger, global::System.Int32 a1)
+ {
+ if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Error))
+ {
+ __M0Callback(logger, a1, null);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// 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 Microsoft.Extensions.Logging.Generators.Tests.TestClasses;
+using Xunit;
+
+namespace Microsoft.Extensions.Logging.Generators.Tests
+{
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)]
+ public class LoggerMessageGeneratedCodeTests
+ {
+ [Fact]
+ public void BasicTests()
+ {
+ var logger = new MockLogger();
+
+ logger.Reset();
+ NoNamespace.CouldNotOpenSocket(logger, "microsoft.com");
+ Assert.Equal(LogLevel.Critical, logger.LastLogLevel);
+ Assert.Null(logger.LastException);
+ Assert.Equal("Could not open socket to `microsoft.com`", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ Level1.OneLevelNamespace.CouldNotOpenSocket(logger, "microsoft.com");
+ Assert.Equal(LogLevel.Critical, logger.LastLogLevel);
+ Assert.Null(logger.LastException);
+ Assert.Equal("Could not open socket to `microsoft.com`", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ Level1.Level2.TwoLevelNamespace.CouldNotOpenSocket(logger, "microsoft.com");
+ Assert.Equal(LogLevel.Critical, logger.LastLogLevel);
+ Assert.Null(logger.LastException);
+ Assert.Equal("Could not open socket to `microsoft.com`", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+ }
+
+ [Fact]
+ public void EnableTest()
+ {
+ var logger = new MockLogger();
+
+ logger.Reset();
+ logger.Enabled = false;
+ NoNamespace.CouldNotOpenSocket(logger, "microsoft.com");
+ Assert.Equal(0, logger.CallCount); // ensure the logger doesn't get called when it is disabled
+ }
+
+ [Fact]
+ public void ArgTest()
+ {
+ var logger = new MockLogger();
+
+ logger.Reset();
+ ArgTestExtensions.Method1(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M1", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ ArgTestExtensions.Method2(logger, "arg1");
+ Assert.Null(logger.LastException);
+ Assert.Equal("M2 arg1", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ ArgTestExtensions.Method3(logger, "arg1", 2);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M3 arg1 2", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ ArgTestExtensions.Method4(logger, new InvalidOperationException("A"));
+ Assert.Equal("A", logger.LastException!.Message);
+ Assert.Equal("M4", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ ArgTestExtensions.Method5(logger, new InvalidOperationException("A"), new InvalidOperationException("B"));
+ Assert.Equal("A", logger.LastException!.Message);
+ Assert.Equal("M5 System.InvalidOperationException: B", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ ArgTestExtensions.Method6(logger, new InvalidOperationException("A"), 2);
+ Assert.Equal("A", logger.LastException!.Message);
+ Assert.Equal("M6 2", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ ArgTestExtensions.Method7(logger, 1, new InvalidOperationException("B"));
+ Assert.Equal("B", logger.LastException!.Message);
+ Assert.Equal("M7 1", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ ArgTestExtensions.Method8(logger, 1, 2, 3, 4, 5, 6, 7);
+ Assert.Equal("M81234567", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ ArgTestExtensions.Method9(logger, 1, 2, 3, 4, 5, 6, 7);
+ Assert.Equal("M9 1 2 3 4 5 6 7", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ ArgTestExtensions.Method10(logger, 1);
+ Assert.Equal("M101", logger.LastFormattedString);
+ Assert.Equal(1, logger.CallCount);
+ }
+
+ [Fact]
+ public void CollectionTest()
+ {
+ var logger = new MockLogger();
+
+ logger.Reset();
+ CollectionTestExtensions.M0(logger);
+ TestCollection(1, logger);
+
+ logger.Reset();
+ CollectionTestExtensions.M1(logger, 0);
+ TestCollection(2, logger);
+
+ logger.Reset();
+ CollectionTestExtensions.M2(logger, 0, 1);
+ TestCollection(3, logger);
+
+ logger.Reset();
+ CollectionTestExtensions.M3(logger, 0, 1, 2);
+ TestCollection(4, logger);
+
+ logger.Reset();
+ CollectionTestExtensions.M4(logger, 0, 1, 2, 3);
+ TestCollection(5, logger);
+
+ logger.Reset();
+ CollectionTestExtensions.M5(logger, 0, 1, 2, 3, 4);
+ TestCollection(6, logger);
+
+ logger.Reset();
+ CollectionTestExtensions.M6(logger, 0, 1, 2, 3, 4, 5);
+ TestCollection(7, logger);
+
+ logger.Reset();
+ CollectionTestExtensions.M7(logger, 0, 1, 2, 3, 4, 5, 6);
+ TestCollection(8, logger);
+
+ logger.Reset();
+ CollectionTestExtensions.M8(logger, 0, 1, 2, 3, 4, 5, 6, 7);
+ TestCollection(9, logger);
+
+ logger.Reset();
+ CollectionTestExtensions.M9(logger, LogLevel.Critical, 0, new ArgumentException("Foo"), 1);
+ TestCollection(3, logger);
+
+ Assert.True(true);
+ }
+
+ [Fact]
+ public void MessageTests()
+ {
+ var logger = new MockLogger();
+
+ logger.Reset();
+ MessageTestExtensions.M0(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal(string.Empty, logger.LastFormattedString);
+ Assert.Equal(LogLevel.Trace, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ MessageTestExtensions.M1(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal(string.Empty, logger.LastFormattedString);
+ Assert.Equal(LogLevel.Debug, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+ }
+
+ [Fact]
+ [ActiveIssue("https://github.com/dotnet/roslyn/issues/52527")]
+ public void MessageTests_SuppressWarning_WarnAsError_NoError()
+ {
+ // Diagnostics produced by source generators do not respect the /warnAsError or /noWarn compiler flags.
+ // These are handled fine by the logger generator and generate warnings. Unfortunately, the warning suppression is
+ // not being observed by the C# compiler at the moment, so having these here causes build warnings.
+#if false
+ var logger = new MockLogger();
+
+ logger.Reset();
+ MessageTestExtensions.M2(logger, "Foo", "Bar");
+ Assert.Null(logger.LastException);
+ Assert.Equal(string.Empty, logger.LastFormattedString);
+ AssertLastState(logger,
+ new KeyValuePair<string, object?>("p1", "Foo"),
+ new KeyValuePair<string, object?>("p2", "Bar"),
+ new KeyValuePair<string, object?>("{OriginalFormat}", string.Empty));
+ Assert.Equal(LogLevel.Trace, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ MessageTestExtensions.M3(logger, "Foo", 42);
+ Assert.Null(logger.LastException);
+ Assert.Equal(string.Empty, logger.LastFormattedString);
+ AssertLastState(logger,
+ new KeyValuePair<string, object?>("p1", "Foo"),
+ new KeyValuePair<string, object?>("p2", 42),
+ new KeyValuePair<string, object?>("{OriginalFormat}", string.Empty));
+ Assert.Equal(LogLevel.Debug, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+#endif
+ }
+
+ [Fact]
+ public void InstanceTests()
+ {
+ var logger = new MockLogger();
+ var o = new TestInstances(logger);
+
+ logger.Reset();
+ o.M0();
+ Assert.Null(logger.LastException);
+ Assert.Equal("M0", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Error, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ o.M1("Foo");
+ Assert.Null(logger.LastException);
+ Assert.Equal("M1 Foo", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Trace, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+ }
+
+ [Fact]
+ public void LevelTests()
+ {
+ var logger = new MockLogger();
+
+ logger.Reset();
+ LevelTestExtensions.M0(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M0", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Trace, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ LevelTestExtensions.M1(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M1", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Debug, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ LevelTestExtensions.M2(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M2", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Information, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ LevelTestExtensions.M3(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M3", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Warning, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ LevelTestExtensions.M4(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M4", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Error, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ LevelTestExtensions.M5(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M5", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Critical, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ LevelTestExtensions.M6(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M6", logger.LastFormattedString);
+ Assert.Equal(LogLevel.None, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ LevelTestExtensions.M7(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M7", logger.LastFormattedString);
+ Assert.Equal((LogLevel)42, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ LevelTestExtensions.M8(logger, LogLevel.Critical);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M8", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Critical, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ LevelTestExtensions.M9(LogLevel.Trace, logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M9", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Trace, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+ }
+
+ [Fact]
+ public void ExceptionTests()
+ {
+ var logger = new MockLogger();
+
+ logger.Reset();
+ ExceptionTestExtensions.M0(logger, new ArgumentException("Foo"), new ArgumentException("Bar"));
+ Assert.Equal("Foo", logger.LastException!.Message);
+ Assert.Equal("M0 System.ArgumentException: Bar", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Trace, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+
+ logger.Reset();
+ ExceptionTestExtensions.M1(new ArgumentException("Foo"), logger, new ArgumentException("Bar"));
+ Assert.Equal("Foo", logger.LastException!.Message);
+ Assert.Equal("M1 System.ArgumentException: Bar", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Debug, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+ }
+
+ [Fact]
+ public void EventNameTests()
+ {
+ var logger = new MockLogger();
+
+ logger.Reset();
+ EventNameTestExtensions.M0(logger);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M0", logger.LastFormattedString);
+ Assert.Equal(LogLevel.Trace, logger.LastLogLevel);
+ Assert.Equal(1, logger.CallCount);
+ Assert.Equal("CustomEventName", logger.LastEventId.Name);
+ }
+
+ [Fact]
+ public void TemplateTests()
+ {
+ var logger = new MockLogger();
+
+ logger.Reset();
+ TemplateTestExtensions.M0(logger, 0);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M0 0", logger.LastFormattedString);
+ AssertLastState(logger,
+ new KeyValuePair<string, object?>("A1", 0),
+ new KeyValuePair<string, object?>("{OriginalFormat}", "M0 {A1}"));
+
+ logger.Reset();
+ TemplateTestExtensions.M1(logger, 42);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M1 42 42", logger.LastFormattedString);
+ AssertLastState(logger,
+ new KeyValuePair<string, object?>("A1", 42),
+ new KeyValuePair<string, object?>("{OriginalFormat}", "M1 {A1} {A1}"));
+
+ logger.Reset();
+ TemplateTestExtensions.M2(logger, 42, 43, 44, 45, 46, 47, 48);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M2 42 43 44 45 46 47 48", logger.LastFormattedString);
+ AssertLastState(logger,
+ new KeyValuePair<string, object?>("A1", 42),
+ new KeyValuePair<string, object?>("a2", 43),
+ new KeyValuePair<string, object?>("A3", 44),
+ new KeyValuePair<string, object?>("a4", 45),
+ new KeyValuePair<string, object?>("A5", 46),
+ new KeyValuePair<string, object?>("a6", 47),
+ new KeyValuePair<string, object?>("A7", 48),
+ new KeyValuePair<string, object?>("{OriginalFormat}", "M2 {A1} {a2} {A3} {a4} {A5} {a6} {A7}"));
+
+ logger.Reset();
+ TemplateTestExtensions.M3(logger, 42, 43);
+ Assert.Null(logger.LastException);
+ Assert.Equal("M3 43 42", logger.LastFormattedString);
+ AssertLastState(logger,
+ new KeyValuePair<string, object?>("A1", 42),
+ new KeyValuePair<string, object?>("a2", 43),
+ new KeyValuePair<string, object?>("{OriginalFormat}", "M3 {a2} {A1}"));
+
+ }
+
+ private static void AssertLastState(MockLogger logger, params KeyValuePair<string, object?>[] expected)
+ {
+ var rol = (IReadOnlyList<KeyValuePair<string, object?>>)logger.LastState!;
+ int count = 0;
+ foreach (var kvp in expected)
+ {
+ Assert.Equal(kvp.Key, rol[count].Key);
+ Assert.Equal(kvp.Value, rol[count].Value);
+ count++;
+ }
+ }
+
+ private static void TestCollection(int expected, MockLogger logger)
+ {
+ var rol = (logger.LastState as IReadOnlyList<KeyValuePair<string, object?>>)!;
+ Assert.NotNull(rol);
+
+ Assert.Equal(expected, rol.Count);
+ for (int i = 0; i < expected; i++)
+ {
+ if (i != expected - 1)
+ {
+ var kvp = new KeyValuePair<string, object?>($"p{i}", i);
+ Assert.Equal(kvp, rol[i]);
+ }
+ }
+
+ int count = 0;
+ foreach (var actual in rol)
+ {
+ if (count != expected - 1)
+ {
+ var kvp = new KeyValuePair<string, object?>($"p{count}", count);
+ Assert.Equal(kvp, actual);
+ }
+
+ count++;
+ }
+
+ Assert.Equal(expected, count);
+ Assert.Throws<IndexOutOfRangeException>(() => rol[expected]);
+ }
+ }
+}
--- /dev/null
+// 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.IO;
+using System.Reflection;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Text;
+using SourceGenerators.Tests;
+using Xunit;
+
+namespace Microsoft.Extensions.Logging.Generators.Tests
+{
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)]
+ public class LoggerMessageGeneratorEmitterTests
+ {
+ [Fact]
+ public async Task TestEmitter()
+ {
+ // The functionality of the resulting code is tested via LoggerMessageGeneratedCodeTests.cs
+ string[] sources = Directory.GetFiles("TestClasses");
+ foreach (var src in sources)
+ {
+ var testSourceCode = await File.ReadAllTextAsync(src).ConfigureAwait(false);
+
+ var (d, r) = await RoslynTestUtils.RunGenerator(
+ new LoggerMessageGenerator(),
+ new[] { typeof(ILogger).Assembly, typeof(LoggerMessageAttribute).Assembly },
+ new[] { testSourceCode }).ConfigureAwait(false);
+
+ Assert.Empty(d);
+ Assert.Single(r);
+ }
+ }
+
+ [Fact]
+ public async Task TestBaseline_TestWithOneParam_Success()
+ {
+ string testSourceCode = @"
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ internal static partial class TestWithOneParam
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Error, Message = ""M0 {A1}"")]
+ public static partial void M0(ILogger logger, int a1);
+ }
+}";
+ await VerifyAgainstBaselineUsingFile("TestWithOneParam.generated.txt", testSourceCode);
+ }
+
+ [Fact]
+ public async Task TestBaseline_TestWithMoreThan6Params_Success()
+ {
+ // TODO: Remove support for more than 6 arguments
+ string testSourceCode = @"
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ internal static partial class TestWithMoreThan6Params
+ {
+ [LoggerMessage(EventId = 8, Level = LogLevel.Error, Message = ""M9 {p1} {p2} {p3} {p4} {p5} {p6} {p7}"")]
+ public static partial void Method9(ILogger logger, int p1, int p2, int p3, int p4, int p5, int p6, int p7);
+ }
+}";
+ await VerifyAgainstBaselineUsingFile("TestWithMoreThan6Params.generated.txt", testSourceCode);
+ }
+
+ [Fact]
+ public async Task TestBaseline_TestWithDynamicLogLevel_Success()
+ {
+ string testSourceCode = @"
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ internal static partial class TestWithDynamicLogLevel
+ {
+ [LoggerMessage(EventId = 9, Message = ""M9"")]
+ public static partial void M9(LogLevel level, ILogger logger);
+ }
+}";
+ await VerifyAgainstBaselineUsingFile("TestWithDynamicLogLevel.generated.txt", testSourceCode);
+ }
+
+ private async Task VerifyAgainstBaselineUsingFile(string filename, string testSourceCode)
+ {
+ string[] expectedLines = await File.ReadAllLinesAsync(Path.Combine("Baselines", filename)).ConfigureAwait(false);
+
+ var (d, r) = await RoslynTestUtils.RunGenerator(
+ new LoggerMessageGenerator(),
+ new[] { typeof(ILogger).Assembly, typeof(LoggerMessageAttribute).Assembly },
+ new[] { testSourceCode }).ConfigureAwait(false);
+
+ Assert.Empty(d);
+ Assert.Single(r);
+
+ Assert.True(CompareLines(expectedLines, r[0].SourceText,
+ out string errorMessage), errorMessage);
+ }
+
+ private bool CompareLines(string[] expectedLines, SourceText sourceText, out string message)
+ {
+ if (expectedLines.Length != sourceText.Lines.Count)
+ {
+ message = string.Format("Line numbers do not match. Expected: {0} lines, but generated {1}",
+ expectedLines.Length, sourceText.Lines.Count);
+ return false;
+ }
+ int index = 0;
+ foreach (TextLine textLine in sourceText.Lines)
+ {
+ string expectedLine = expectedLines[index];
+ if (!expectedLine.Equals(textLine.ToString(), StringComparison.Ordinal))
+ {
+ message = string.Format("Line {0} does not match.{1}Expected Line:{1}{2}{1}Actual Line:{1}{3}",
+ textLine.LineNumber, Environment.NewLine, expectedLine, textLine);
+ return false;
+ }
+ index++;
+ }
+ message = string.Empty;
+ return true;
+ }
+ }
+}
--- /dev/null
+// 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.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using SourceGenerators.Tests;
+using Xunit;
+
+namespace Microsoft.Extensions.Logging.Generators.Tests
+{
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)]
+ public class LoggerMessageGeneratorParserTests
+ {
+ [Fact]
+ public async Task InvalidMethodName()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ static partial void __M1(ILogger logger);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.InvalidLoggingMethodName.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task MissingLogLevel()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Message = ""M1"")]
+ static partial void M1(ILogger logger);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.MissingLogLevel.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task InvalidMethodBody()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ static partial void M1(ILogger logger);
+
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ static partial void M1(ILogger logger)
+ {
+ }
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.LoggingMethodHasBody.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task MissingTemplate()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""This is a message without foo"")]
+ static partial void M1(ILogger logger, string foo);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.ArgumentHasNoCorrespondingTemplate.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task MissingArgument()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""{foo}"")]
+ static partial void M1(ILogger logger);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.TemplateHasNoCorrespondingArgument.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task NeedlessQualifierInMessage()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Information, Message = ""INFO: this is an informative message"")]
+ static partial void M1(ILogger logger);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.RedundantQualifierInMessage.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task NeedlessExceptionInMessage()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {ex} {ex2}"")]
+ static partial void M1(ILogger logger, System.Exception ex, System.Exception ex2);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.ShouldntMentionExceptionInMessage.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task NeedlessLogLevelInMessage()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Message = ""M1 {l1} {l2}"")]
+ static partial void M1(ILogger logger, LogLevel l1, LogLevel l2);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.ShouldntMentionLogLevelInMessage.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task NeedlessLoggerInMessage()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {logger}"")]
+ static partial void M1(ILogger logger);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.ShouldntMentionLoggerInMessage.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task DoubleLogLevel_InAttributeAndAsParameterButMissingInTemplate_ProducesDiagnostic()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ static partial void M1(ILogger logger, LogLevel levelParam);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.ArgumentHasNoCorrespondingTemplate.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task LogLevelDoublySet_AndInMessageTemplate_ProducesDiagnostic()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {level2}"")]
+ static partial void M1(ILogger logger, LogLevel level1, LogLevel level2);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.ArgumentHasNoCorrespondingTemplate.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task DoubleLogLevel_FirstOneSetAsMethodParameter_SecondOneInMessageTemplate_Supported()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Message = ""M1 {level2}"")]
+ static partial void M1(ILogger logger, LogLevel level1, LogLevel level2);
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+#if false
+ // TODO: can't have the same template with different casing
+ [Fact]
+ public async Task InconsistentTemplateCasing()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {p1} {P1}"")]
+ static partial void M1(ILogger logger, int p1, int P1);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.InconsistentTemplateCasing.Id, diagnostics[0].Id);
+ }
+
+ // TODO: can't have malformed format strings (like dangling {, etc)
+ [Fact]
+ public async Task MalformedFormatString()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {p1} {P1}"")]
+ static partial void M1(ILogger logger, int p1, int P1);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.MalformedFormatStrings.Id, diagnostics[0].Id);
+ }
+#endif
+
+ [Fact]
+ public async Task InvalidParameterName()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {__foo}"")]
+ static partial void M1(ILogger logger, string __foo);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.InvalidLoggingMethodParameterName.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task NestedType()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ public partial class Nested
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ static partial void M1(ILogger logger);
+ }
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.LoggingMethodInNestedType.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task MissingExceptionType()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ namespace System
+ {
+ public class Object {}
+ public class Void {}
+ public class String {}
+ public struct DateTime {}
+ }
+ namespace System.Collections
+ {
+ public interface IEnumerable {}
+ }
+ namespace Microsoft.Extensions.Logging
+ {
+ public enum LogLevel {}
+ public interface ILogger {}
+ }
+ namespace Microsoft.Extensions.Logging
+ {
+ public class LoggerMessageAttribute {}
+ }
+ partial class C
+ {
+ }
+ ", false, includeBaseReferences: false, includeLoggingReferences: false);
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.MissingRequiredType.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task MissingStringType()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ namespace System
+ {
+ public class Object {}
+ public class Void {}
+ public class Exception {}
+ public struct DateTime {}
+ }
+ namespace System.Collections
+ {
+ public interface IEnumerable {}
+ }
+ namespace Microsoft.Extensions.Logging
+ {
+ public enum LogLevel {}
+ public interface ILogger {}
+ }
+ namespace Microsoft.Extensions.Logging
+ {
+ public class LoggerMessageAttribute {}
+ }
+ partial class C
+ {
+ }
+ ", false, includeBaseReferences: false, includeLoggingReferences: false);
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.MissingRequiredType.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task MissingEnumerableType()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ namespace System
+ {
+ public class Object {}
+ public class Void {}
+ public class Exception {}
+ public struct DateTime {}
+ public class String {}
+ }
+ namespace Microsoft.Extensions.Logging
+ {
+ public enum LogLevel {}
+ public interface ILogger {}
+ }
+ namespace Microsoft.Extensions.Logging
+ {
+ public class LoggerMessageAttribute {}
+ }
+ partial class C
+ {
+ }
+ ", false, includeBaseReferences: false, includeLoggingReferences: false);
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.MissingRequiredType.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task MissingLoggerMessageAttributeType()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ }
+ ", false, includeLoggingReferences: false);
+
+ Assert.Empty(diagnostics);
+ }
+
+ [Fact]
+ public async Task MissingILoggerType()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ namespace Microsoft.Extensions.Logging
+ {
+ public sealed class LoggerMessageAttribute : System.Attribute {}
+ }
+ partial class C
+ {
+ }
+ ", false, includeLoggingReferences: false);
+
+ Assert.Empty(diagnostics);
+ }
+
+ [Fact]
+ public async Task MissingLogLevelType()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ namespace Microsoft.Extensions.Logging
+ {
+ public sealed class LoggerMessageAttribute : System.Attribute {}
+ }
+ namespace Microsoft.Extensions.Logging
+ {
+ public interface ILogger {}
+ }
+ partial class C
+ {
+ }
+ ", false, includeLoggingReferences: false);
+
+ Assert.Empty(diagnostics);
+ }
+
+ [Fact]
+ public async Task EventIdReuse()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class MyClass
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ static partial void M1(ILogger logger);
+
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ static partial void M2(ILogger logger);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.ShouldntReuseEventIds.Id, diagnostics[0].Id);
+ Assert.Contains("in class MyClass", diagnostics[0].GetMessage(), StringComparison.InvariantCulture);
+ }
+
+ [Fact]
+ public async Task MethodReturnType()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ public static partial int M1(ILogger logger);
+
+ public static partial int M1(ILogger logger) { return 0; }
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.LoggingMethodMustReturnVoid.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task MissingILogger()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {p1}"")]
+ static partial void M1(int p1);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.MissingLoggerArgument.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task NotStatic()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ partial void M1(ILogger logger);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.LoggingMethodShouldBeStatic.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task NoILoggerField()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ public partial void M1();
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.MissingLoggerField.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task MultipleILoggerFields()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ public ILogger _logger1;
+ public ILogger _logger2;
+
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ public partial void M1();
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.MultipleLoggerFields.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task NotPartial()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ static void M1(ILogger logger) {}
+ }
+ ");
+
+ Assert.Equal(2, diagnostics.Count);
+ Assert.Equal(DiagnosticDescriptors.LoggingMethodMustBePartial.Id, diagnostics[0].Id);
+ Assert.Equal(DiagnosticDescriptors.LoggingMethodHasBody.Id, diagnostics[1].Id);
+ }
+
+ [Fact]
+ public async Task MethodGeneric()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ static partial void M1<T>(ILogger logger);
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagnosticDescriptors.LoggingMethodIsGeneric.Id, diagnostics[0].Id);
+ }
+
+ [Fact]
+ public async Task Templates()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = ""M1"")]
+ static partial void M1(ILogger logger);
+
+ [LoggerMessage(EventId = 2, Level = LogLevel.Debug, Message = ""M2 {arg1} {arg2}"")]
+ static partial void M2(ILogger logger, string arg1, string arg2);
+
+ [LoggerMessage(EventId = 3, Level = LogLevel.Debug, Message = ""M3 {arg1"")]
+ static partial void M3(ILogger logger);
+
+ [LoggerMessage(EventId = 4, Level = LogLevel.Debug, Message = ""M4 arg1}"")]
+ static partial void M4(ILogger logger);
+
+ [LoggerMessage(EventId = 5, Level = LogLevel.Debug, Message = ""M5 {"")]
+ static partial void M5(ILogger logger);
+
+ [LoggerMessage(EventId = 6, Level = LogLevel.Debug, Message = ""}M6 "")]
+ static partial void M6(ILogger logger);
+
+ [LoggerMessage(EventId = 7, Level = LogLevel.Debug, Message = ""M7 {{arg1}}"")]
+ static partial void M7(ILogger logger);
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+ [Fact]
+ public async Task Cancellation()
+ {
+ await Assert.ThrowsAsync<OperationCanceledException>(async () =>
+ await RunGenerator(@"
+ partial class C
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ static partial void M1(ILogger logger);
+ }
+ ", cancellationToken: new CancellationToken(true)));
+ }
+
+ [Fact]
+ public async Task SourceErrors()
+ {
+ IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+ static partial class C
+ {
+ // bogus argument type
+ [LoggerMessage(EventId = 0, Level = "", Message = ""Hello"")]
+ static partial void M1(ILogger logger);
+
+ // missing parameter name
+ [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = ""Hello"")]
+ static partial void M2(ILogger);
+
+ // bogus parameter type
+ [LoggerMessage(EventId = 2, Level = LogLevel.Debug, Message = ""Hello"")]
+ static partial void M3(XILogger logger);
+
+ // attribute applied to something other than a method
+ [LoggerMessage(EventId = 4, Message = ""Hello"")]
+ int M5;
+ }
+ ");
+
+ Assert.Empty(diagnostics); // should fail quietly on broken code
+ }
+
+ private static async Task<IReadOnlyList<Diagnostic>> RunGenerator(
+ string code,
+ bool wrap = true,
+ bool inNamespace = true,
+ bool includeBaseReferences = true,
+ bool includeLoggingReferences = true,
+ CancellationToken cancellationToken = default)
+ {
+ var text = code;
+ if (wrap)
+ {
+ var nspaceStart = "namespace Test {";
+ var nspaceEnd = "}";
+ if (!inNamespace)
+ {
+ nspaceStart = "";
+ nspaceEnd = "";
+ }
+
+ text = $@"
+ {nspaceStart}
+ using Microsoft.Extensions.Logging;
+ {code}
+ {nspaceEnd}
+ ";
+ }
+
+ Assembly[]? refs = null;
+ if (includeLoggingReferences)
+ {
+ refs = new[] { typeof(ILogger).Assembly, typeof(LoggerMessageAttribute).Assembly };
+ }
+
+ var (d, r) = await RoslynTestUtils.RunGenerator(
+ new LoggerMessageGenerator(),
+ refs,
+ new[] { text },
+ includeBaseReferences: includeBaseReferences,
+ cancellationToken: cancellationToken).ConfigureAwait(false);
+
+ return d;
+ }
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFrameworks>$(NetCoreAppCurrent)</TargetFrameworks>
+ <EnableDefaultItems>true</EnableDefaultItems>
+ <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
+ <Nullable>enable</Nullable>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="$(CommonPath)..\tests\SourceGenerators\RoslynTestUtils.cs"
+ Link="SourceGenerators\RoslynTestUtils.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Logging\src\Microsoft.Extensions.Logging.csproj" />
+ <PackageReference Include="Microsoft.CodeAnalysis" Version="$(MicrosoftCodeAnalysisVersion)" />
+ <PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawbundle_greenVersion)" />
+ <ProjectReference Include="..\..\gen\Microsoft.Extensions.Logging.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="true" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Content Include="TestClasses\*.cs">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="Baselines\*.generated.txt">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ </ItemGroup>
+
+</Project>
--- /dev/null
+// 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 Microsoft.Extensions.Logging;
+
+namespace Microsoft.Extensions.Logging.Generators.Tests
+{
+ /// <summary>
+ /// A logger which captures the last log state logged to it.
+ /// </summary>
+ internal class MockLogger : ILogger
+ {
+ public LogLevel LastLogLevel { get; private set; }
+ public EventId LastEventId { get; private set; }
+ public object? LastState { get; private set; }
+ public Exception? LastException { get; private set; }
+ public string? LastFormattedString { get; private set; }
+ public bool Enabled { get; set; }
+ public int CallCount { get; private set; }
+
+ /// <summary>
+ /// Dummy disposable type, for use with BeginScope.
+ /// </summary>
+ private class Disposable : IDisposable
+ {
+ public void Dispose()
+ {
+ // nothing
+ }
+ }
+
+ public MockLogger()
+ {
+ Reset();
+ }
+
+ public IDisposable BeginScope<TState>(TState state)
+ {
+ return new Disposable();
+ }
+
+ public bool IsEnabled(LogLevel logLevel)
+ {
+ return Enabled;
+ }
+
+ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
+ {
+ LastLogLevel = logLevel;
+ LastEventId = eventId;
+ LastState = state;
+ LastException = exception;
+ LastFormattedString = formatter(state, exception);
+ CallCount++;
+ }
+
+ public void Reset()
+ {
+ LastLogLevel = (LogLevel)(-1);
+ LastEventId = default;
+ LastState = null;
+ LastException = null;
+ LastFormattedString = null;
+ CallCount = 0;
+ Enabled = true;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ internal static partial class ArgTestExtensions
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Error, Message = "M1")]
+ public static partial void Method1(ILogger logger);
+
+ [LoggerMessage(EventId = 1, Level = LogLevel.Error, Message = "M2 {p1}")]
+ public static partial void Method2(ILogger logger, string p1);
+
+ [LoggerMessage(EventId = 2, Level = LogLevel.Error, Message = "M3 {p1} {p2}")]
+ public static partial void Method3(ILogger logger, string p1, int p2);
+
+ [LoggerMessage(EventId = 3, Level = LogLevel.Error, Message = "M4")]
+ public static partial void Method4(ILogger logger, InvalidOperationException p1);
+
+ [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "M5 {p2}")]
+ public static partial void Method5(ILogger logger, System.InvalidOperationException p1, System.InvalidOperationException p2);
+
+ [LoggerMessage(EventId = 5, Level = LogLevel.Error, Message = "M6 {p2}")]
+ public static partial void Method6(ILogger logger, System.InvalidOperationException p1, int p2);
+
+ [LoggerMessage(EventId = 6, Level = LogLevel.Error, Message = "M7 {p1}")]
+ public static partial void Method7(ILogger logger, int p1, System.InvalidOperationException p2);
+
+ [LoggerMessage(EventId = 7, Level = LogLevel.Error, Message = "M8{p1}{p2}{p3}{p4}{p5}{p6}{p7}")]
+ public static partial void Method8(ILogger logger, int p1, int p2, int p3, int p4, int p5, int p6, int p7);
+
+ [LoggerMessage(EventId = 8, Level = LogLevel.Error, Message = "M9 {p1} {p2} {p3} {p4} {p5} {p6} {p7}")]
+ public static partial void Method9(ILogger logger, int p1, int p2, int p3, int p4, int p5, int p6, int p7);
+
+ [LoggerMessage(EventId = 9, Level = LogLevel.Error, Message = "M10{p1}")]
+ public static partial void Method10(ILogger logger, int p1);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ internal static partial class CollectionTestExtensions
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Error, Message = "M0")]
+ public static partial void M0(ILogger logger);
+
+ [LoggerMessage(EventId = 1, Level = LogLevel.Error, Message = "M1{p0}")]
+ public static partial void M1(ILogger logger, int p0);
+
+ [LoggerMessage(EventId = 2, Level = LogLevel.Error, Message = "M2{p0}{p1}")]
+ public static partial void M2(ILogger logger, int p0, int p1);
+
+ [LoggerMessage(EventId = 3, Level = LogLevel.Error, Message = "M3{p0}{p1}{p2}")]
+ public static partial void M3(ILogger logger, int p0, int p1, int p2);
+
+ [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "M4{p0}{p1}{p2}{p3}")]
+ public static partial void M4(ILogger logger, int p0, int p1, int p2, int p3);
+
+ [LoggerMessage(EventId = 5, Level = LogLevel.Error, Message = "M5{p0}{p1}{p2}{p3}{p4}")]
+ public static partial void M5(ILogger logger, int p0, int p1, int p2, int p3, int p4);
+
+ [LoggerMessage(EventId = 6, Level = LogLevel.Error, Message = "M6{p0}{p1}{p2}{p3}{p4}{p5}")]
+ public static partial void M6(ILogger logger, int p0, int p1, int p2, int p3, int p4, int p5);
+
+ [LoggerMessage(EventId = 7, Level = LogLevel.Error, Message = "M7{p0}{p1}{p2}{p3}{p4}{p5}{p6}")]
+ public static partial void M7(ILogger logger, int p0, int p1, int p2, int p3, int p4, int p5, int p6);
+
+ [LoggerMessage(EventId = 8, Level = LogLevel.Error, Message = "M8{p0}{p1}{p2}{p3}{p4}{p5}{p6}{p7}")]
+ public static partial void M8(ILogger logger, int p0, int p1, int p2, int p3, int p4, int p5, int p6, int p7);
+
+ [LoggerMessage(EventId = 9, Message = "M8{p0}{p1}")]
+ public static partial void M9(ILogger logger, LogLevel level, int p0, System.Exception ex, int p1);
+ }
+}
--- /dev/null
+// 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;
+using System.Collections.Generic;
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ internal static partial class EnumerableTestExtensions
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Error, Message = "M0")]
+ public static partial void M0(ILogger logger);
+
+ [LoggerMessage(EventId = 1, Level = LogLevel.Error, Message = "M1{p0}")]
+ public static partial void M1(ILogger logger, IEnumerable<int> p0);
+
+ [LoggerMessage(EventId = 2, Level = LogLevel.Error, Message = "M2{p0}{p1}")]
+ public static partial void M2(ILogger logger, int p0, IEnumerable<int> p1);
+
+ [LoggerMessage(EventId = 3, Level = LogLevel.Error, Message = "M3{p0}{p1}{p2}")]
+ public static partial void M3(ILogger logger, int p0, IEnumerable<int> p1, int p2);
+
+ [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "M4{p0}{p1}{p2}{p3}")]
+ public static partial void M4(ILogger logger, int p0, IEnumerable<int> p1, int p2, int p3);
+
+ [LoggerMessage(EventId = 5, Level = LogLevel.Error, Message = "M5{p0}{p1}{p2}{p3}{p4}")]
+ public static partial void M5(ILogger logger, int p0, IEnumerable<int> p1, int p2, int p3, int p4);
+
+ [LoggerMessage(EventId = 6, Level = LogLevel.Error, Message = "M6{p0}{p1}{p2}{p3}{p4}{p5}")]
+ public static partial void M6(ILogger logger, int p0, IEnumerable<int> p1, int p2, int p3, int p4, int p5);
+
+ [LoggerMessage(EventId = 7, Level = LogLevel.Error, Message = "M7{p0}{p1}{p2}{p3}{p4}{p5}{p6}")]
+ public static partial void M7(ILogger logger, int p0, IEnumerable<int> p1, int p2, int p3, int p4, int p5, int p6);
+
+ [LoggerMessage(EventId = 8, Level = LogLevel.Error, Message = "M8{p0}{p1}{p2}{p3}{p4}{p5}{p6}{p7}")]
+ public static partial void M8(ILogger logger, int p0, IEnumerable<int> p1, int p2, int p3, int p4, int p5, int p6, int p7);
+
+ [LoggerMessage(EventId = 9, Level = LogLevel.Error, Message = "M9{p0}{p1}{p2}{p3}{p4}{p5}{p6}{p7}{p8}")]
+ public static partial void M9(ILogger logger, int p0, IEnumerable<int> p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ internal static partial class EventNameTestExtensions
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Trace, Message = "M0", EventName = "CustomEventName")]
+ public static partial void M0(ILogger logger);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ internal static partial class ExceptionTestExtensions
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Trace, Message = "M0 {ex2}")]
+ public static partial void M0(ILogger logger, Exception ex1, Exception ex2);
+
+ [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "M1 {ex2}")]
+ public static partial void M1(Exception ex1, ILogger logger, Exception ex2);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ internal static partial class LevelTestExtensions
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Trace, Message = "M0")]
+ public static partial void M0(ILogger logger);
+
+ [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "M1")]
+ public static partial void M1(ILogger logger);
+
+ [LoggerMessage(EventId = 2, Level = LogLevel.Information, Message = "M2")]
+ public static partial void M2(ILogger logger);
+
+ [LoggerMessage(EventId = 3, Level = LogLevel.Warning, Message = "M3")]
+ public static partial void M3(ILogger logger);
+
+ [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "M4")]
+ public static partial void M4(ILogger logger);
+
+ [LoggerMessage(EventId = 5, Level = LogLevel.Critical, Message = "M5")]
+ public static partial void M5(ILogger logger);
+
+ [LoggerMessage(EventId = 6, Level = LogLevel.None, Message = "M6")]
+ public static partial void M6(ILogger logger);
+
+ [LoggerMessage(EventId = 7, Level = (LogLevel)42, Message = "M7")]
+ public static partial void M7(ILogger logger);
+
+ [LoggerMessage(EventId = 8, Message = "M8")]
+ public static partial void M8(ILogger logger, LogLevel level);
+
+ [LoggerMessage(EventId = 9, Message = "M9")]
+ public static partial void M9(LogLevel level, ILogger logger);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#pragma warning disable SYSLIB0027
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ internal static partial class MessageTestExtensions
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Trace)]
+ public static partial void M0(ILogger logger);
+
+ [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "")]
+ public static partial void M1(ILogger logger);
+
+#if false
+ // Diagnostics produced by source generators do not respect the /warnAsError or /noWarn compiler flags.
+ // Disabled due to https://github.com/dotnet/roslyn/issues/52527
+ //
+ // These are handled fine by the logger generator and generate warnings. Unfortunately, the above warning suppression is
+ // not being observed by the C# compiler at the moment, so having these here causes build warnings.
+
+ [LoggerMessage(EventId = 2, Level = LogLevel.Trace)]
+ public static partial void M2(ILogger logger, string p1, string p2);
+
+ [LoggerMessage(EventId = 3, Level = LogLevel.Debug, Message = "")]
+ public static partial void M3(ILogger logger, string p1, int p2);
+
+ [LoggerMessage(EventId = 4, Level = LogLevel.Debug, Message = "{p1}")]
+ public static partial void M4(ILogger logger, string p1, int p2, int p3);
+#endif
+ }
+}
--- /dev/null
+// 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;
+
+// Used to test use outside of a namespace
+internal static partial class NoNamespace
+{
+ [LoggerMessage(EventId = 0, Level = LogLevel.Critical, Message = "Could not open socket to `{hostName}`")]
+ public static partial void CouldNotOpenSocket(ILogger logger, string hostName);
+}
+
+namespace Level1
+{
+ // used to test use inside a one-level namespace
+ internal static partial class OneLevelNamespace
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Critical, Message = "Could not open socket to `{hostName}`")]
+ public static partial void CouldNotOpenSocket(ILogger logger, string hostName);
+ }
+}
+
+namespace Level1
+{
+ namespace Level2
+ {
+ // used to test use inside a two-level namespace
+ internal static partial class TwoLevelNamespace
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Critical, Message = "Could not open socket to `{hostName}`")]
+ public static partial void CouldNotOpenSocket(ILogger logger, string hostName);
+ }
+ }
+}
--- /dev/null
+The source files in this directory serve two purposes:
+
+1. They are used to trigger the source generator during compilation of the test suite itself. The resulting generated code
+is then tested by LoggerMessageGeneratedCodeTests.cs. This ensures the generated code works reliably.
+
+2.They are loaded as a file from `LoggerMessageGeneratorEmitterTests.cs`, and then fed manually to the parser and then the generator
+This is used strictly to calculate code coverage attained by the first case above.
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ // test particular method signature variations are generated correctly
+ internal static partial class SignatureTestExtensions
+ {
+ // extension method
+ [LoggerMessage(EventId = 10, Level = LogLevel.Critical, Message = "Message11")]
+ internal static partial void M11(this ILogger logger);
+
+ public static void Combo(ILogger logger)
+ {
+ logger.M11();
+ }
+ }
+
+ // test particular method signature variations are generated correctly
+ internal partial class SignatureTestExtensions<T>
+ where T : class
+ {
+ public static void Combo(ILogger logger, ILogger<int> logger2)
+ {
+ M1(logger);
+ M2(logger);
+ M3(logger);
+ M4(logger2);
+ M5(logger, new[] { "A" });
+ M6(logger);
+ M8(logger);
+ M9(logger);
+ M10(logger, null);
+ M11(logger, "A", LogLevel.Debug, "B");
+ }
+
+ // normal public method
+ [LoggerMessage(EventId = 0, Level = LogLevel.Critical, Message = "Message1")]
+ public static partial void M1(ILogger logger);
+
+ // internal method
+ [LoggerMessage(EventId = 1, Level = LogLevel.Critical, Message = "Message2")]
+ internal static partial void M2(ILogger logger);
+
+ // private method
+ [LoggerMessage(EventId = 2, Level = LogLevel.Critical, Message = "Message3")]
+ private static partial void M3(ILogger logger);
+
+ // generic ILogger
+ [LoggerMessage(EventId = 3, Level = LogLevel.Critical, Message = "Message4")]
+ private static partial void M4(ILogger<int> logger);
+
+ // random type method parameter
+ [LoggerMessage(EventId = 4, Level = LogLevel.Critical, Message = "Message5 {items}")]
+ private static partial void M5(ILogger logger, System.Collections.IEnumerable items);
+
+ // line feeds and quotes in the message string
+ [LoggerMessage(EventId = 5, Level = LogLevel.Critical, Message = "Message6\n\"\r")]
+ private static partial void M6(ILogger logger);
+
+ // generic parameter
+ [LoggerMessage(EventId = 6, Level = LogLevel.Critical, Message = "Message7 {p1}\n\"\r")]
+ private static partial void M7(ILogger logger, T p1);
+
+ // normal public method
+ [LoggerMessage(EventId = 7, Level = LogLevel.Critical, Message = "Message8")]
+ private protected static partial void M8(ILogger logger);
+
+ // internal method
+ [LoggerMessage(EventId = 8, Level = LogLevel.Critical, Message = "Message9")]
+ protected internal static partial void M9(ILogger logger);
+
+ // nullable parameter
+ [LoggerMessage(EventId = 9, Level = LogLevel.Critical, Message = "Message10 {optional}")]
+ internal static partial void M10(ILogger logger, string? optional);
+
+ // dynamic log level
+ [LoggerMessage(EventId = 10, Message = "Message11 {p1} {p2}")]
+ internal static partial void M11(ILogger logger, string p1, LogLevel level, string p2);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ internal static partial class TemplateTestExtensions
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Error, Message = "M0 {A1}")]
+ public static partial void M0(ILogger logger, int a1);
+
+ [LoggerMessage(EventId = 1, Level = LogLevel.Error, Message = "M1 {A1} {A1}")]
+ public static partial void M1(ILogger logger, int a1);
+
+ [LoggerMessage(EventId = 2, Level = LogLevel.Error, Message = "M2 {A1} {a2} {A3} {a4} {A5} {a6} {A7}")]
+ public static partial void M2(ILogger logger, int a1, int a2, int a3, int a4, int a5, int a6, int a7);
+
+ [LoggerMessage(EventId = 3, Level = LogLevel.Error, Message = "M3 {a2} {A1}")]
+ public static partial void M3(ILogger logger, int a1, int a2);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ public partial class TestInstances
+ {
+ private readonly ILogger _myLogger;
+
+ public TestInstances(ILogger logger)
+ {
+ _myLogger = logger;
+ }
+
+ [LoggerMessage(EventId = 0, Level = LogLevel.Error, Message = "M0")]
+ public partial void M0();
+
+ [LoggerMessage(EventId = 1, Level = LogLevel.Trace, Message = "M1 {p1}")]
+ public partial void M1(string p1);
+ }
+}
Exclude="@(ProjectExclusions)" />
<NonNetCoreAppProject Include="@(_allSrc)"
Exclude="@(NetCoreAppLibrary->'%(Identity)\src\%(Identity).csproj')" />
+ <NonNetCoreAppProject Include="$(MSBuildThisFileDirectory)*\gen\*.csproj"
+ Exclude="@(ProjectExclusions)" />
<NetCoreAppProject Include="$(CoreLibProject);
@(_allSrc);
$(MSBuildThisFileDirectory)Microsoft.VisualBasic.Core\src\Microsoft.VisualBasic.Core.vbproj;
<TestTrimming Condition="'$(TestTrimming)' == ''">false</TestTrimming>
</PropertyGroup>
+ <ItemGroup Condition="'$(TargetsMobile)' == 'true'">
+ <!-- Microsoft.CodeAnalysis.* assemblies missing in the virtual file system for Browser and the bundle for the mobile platforms -->
+ <ProjectExclusions Include="$(MSBuildThisFileDirectory)Microsoft.Extensions.Logging\tests\Microsoft.Extensions.Logging.Generators.Tests\Microsoft.Extensions.Logging.Generators.Tests.csproj" />
+ </ItemGroup>
+
<!-- Projects that don't support code coverage measurement. -->
<ItemGroup Condition="'$(Coverage)' == 'true'">
<ProjectExclusions Include="$(CommonTestPath)Common.Tests.csproj" />