From: Maryam Ariyan Date: Tue, 15 Jun 2021 22:36:02 +0000 (-0400) Subject: Support generating log methods in nested classes (#54180) X-Git-Tag: submit/tizen/20210909.063632~744 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d0ca735b38a1fe279a05ea0c27370a2f117f5b35;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Support generating log methods in nested classes (#54180) --- diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs index 2e7e0ac..2e3f31a 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs @@ -32,14 +32,6 @@ namespace Microsoft.Extensions.Logging.Generators 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)), diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs index 748bfd3..2b0bc4e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs @@ -65,6 +65,7 @@ namespace Microsoft.Extensions.Logging.Generators private void GenType(LoggerClass lc) { + string nestedIndentation = ""; if (!string.IsNullOrWhiteSpace(lc.Namespace)) { _builder.Append($@" @@ -72,22 +73,49 @@ namespace {lc.Namespace} {{"); } + LoggerClass parent = lc.ParentClass; + var parentClasses = new List(); + // loop until you find top level nested class + while (parent != null) + { + parentClasses.Add($"partial {parent.Keyword} {parent.Name} {parent.Constraints}"); + parent = parent.ParentClass; + } + + // write down top level nested class first + for (int i = parentClasses.Count - 1; i >= 0; i--) + { + _builder.Append($@" + {nestedIndentation}{parentClasses[i]} + {nestedIndentation}{{"); + nestedIndentation += " "; + } + _builder.Append($@" - partial class {lc.Name} {lc.Constraints} - {{"); + {nestedIndentation}partial {lc.Keyword} {lc.Name} {lc.Constraints} + {nestedIndentation}{{"); foreach (LoggerMethod lm in lc.Methods) { if (!UseLoggerMessageDefine(lm)) { - GenStruct(lm); + GenStruct(lm, nestedIndentation); } - GenLogMethod(lm); + GenLogMethod(lm, nestedIndentation); } _builder.Append($@" - }}"); + {nestedIndentation}}}"); + + parent = lc.ParentClass; + while (parent != null) + { + nestedIndentation = new String(' ', nestedIndentation.Length - 4); + _builder.Append($@" + {nestedIndentation}}}"); + parent = parent.ParentClass; + } if (!string.IsNullOrWhiteSpace(lc.Namespace)) { @@ -96,83 +124,83 @@ namespace {lc.Namespace} } } - private void GenStruct(LoggerMethod lm) + private void GenStruct(LoggerMethod lm, string nestedIndentation) { _builder.AppendLine($@" - [{s_generatedCodeAttribute}] - private readonly struct __{lm.Name}Struct : global::System.Collections.Generic.IReadOnlyList> - {{"); - GenFields(lm); + {nestedIndentation}[{s_generatedCodeAttribute}] + {nestedIndentation}private readonly struct __{lm.Name}Struct : global::System.Collections.Generic.IReadOnlyList> + {nestedIndentation}{{"); + GenFields(lm, nestedIndentation); if (lm.TemplateParameters.Count > 0) { _builder.Append($@" - public __{lm.Name}Struct("); + {nestedIndentation}public __{lm.Name}Struct("); GenArguments(lm); _builder.Append($@") - {{"); + {nestedIndentation}{{"); _builder.AppendLine(); - GenFieldAssignments(lm); + GenFieldAssignments(lm, nestedIndentation); _builder.Append($@" - }} + {nestedIndentation}}} "); } _builder.Append($@" - public override string ToString() - {{ + {nestedIndentation}public override string ToString() + {nestedIndentation}{{ "); - GenVariableAssignments(lm); + GenVariableAssignments(lm, nestedIndentation); _builder.Append($@" - return $""{lm.Message}""; - }} + {nestedIndentation}return $""{lm.Message}""; + {nestedIndentation}}} "); _builder.Append($@" - public static string Format(__{lm.Name}Struct state, global::System.Exception? ex) => state.ToString(); + {nestedIndentation}public static string Format(__{lm.Name}Struct state, global::System.Exception? ex) => state.ToString(); - public int Count => {lm.TemplateParameters.Count + 1}; + {nestedIndentation}public int Count => {lm.TemplateParameters.Count + 1}; - public global::System.Collections.Generic.KeyValuePair this[int index] - {{ - get => index switch - {{ + {nestedIndentation}public global::System.Collections.Generic.KeyValuePair this[int index] + {nestedIndentation}{{ + {nestedIndentation}get => index switch + {nestedIndentation}{{ "); - GenCases(lm); + GenCases(lm, nestedIndentation); _builder.Append($@" - _ => throw new global::System.IndexOutOfRangeException(nameof(index)), // return the same exception LoggerMessage.Define returns in this case - }}; + {nestedIndentation}_ => throw new global::System.IndexOutOfRangeException(nameof(index)), // return the same exception LoggerMessage.Define returns in this case + {nestedIndentation}}}; }} - public global::System.Collections.Generic.IEnumerator> GetEnumerator() - {{ - for (int i = 0; i < {lm.TemplateParameters.Count + 1}; i++) - {{ - yield return this[i]; - }} - }} + {nestedIndentation}public global::System.Collections.Generic.IEnumerator> GetEnumerator() + {nestedIndentation}{{ + {nestedIndentation}for (int i = 0; i < {lm.TemplateParameters.Count + 1}; i++) + {nestedIndentation}{{ + {nestedIndentation}yield return this[i]; + {nestedIndentation}}} + {nestedIndentation}}} - global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); - }} + {nestedIndentation}global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + {nestedIndentation}}} "); } - private void GenFields(LoggerMethod lm) + private void GenFields(LoggerMethod lm, string nestedIndentation) { foreach (LoggerParameter p in lm.TemplateParameters) { - _builder.AppendLine($" private readonly {p.Type} _{p.Name};"); + _builder.AppendLine($" {nestedIndentation}private readonly {p.Type} _{p.Name};"); } } - private void GenFieldAssignments(LoggerMethod lm) + private void GenFieldAssignments(LoggerMethod lm, string nestedIndentation) { foreach (LoggerParameter p in lm.TemplateParameters) { - _builder.AppendLine($" this._{p.Name} = {p.Name};"); + _builder.AppendLine($" {nestedIndentation}this._{p.Name} = {p.Name};"); } } - private void GenVariableAssignments(LoggerMethod lm) + private void GenVariableAssignments(LoggerMethod lm, string nestedIndentation) { foreach (KeyValuePair t in lm.TemplateMap) { @@ -192,20 +220,20 @@ namespace {lc.Namespace} { if (lm.TemplateParameters[index].IsEnumerable) { - _builder.AppendLine($" var {t.Key} = " + _builder.AppendLine($" {nestedIndentation}var {t.Key} = " + $"global::__LoggerMessageGenerator.Enumerate((global::System.Collections.IEnumerable ?)this._{lm.TemplateParameters[index].Name});"); _needEnumerationHelper = true; } else { - _builder.AppendLine($" var {t.Key} = this._{lm.TemplateParameters[index].Name};"); + _builder.AppendLine($" {nestedIndentation}var {t.Key} = this._{lm.TemplateParameters[index].Name};"); } } } } - private void GenCases(LoggerMethod lm) + private void GenCases(LoggerMethod lm, string nestedIndentation) { int index = 0; foreach (LoggerParameter p in lm.TemplateParameters) @@ -217,10 +245,10 @@ namespace {lc.Namespace} name = lm.TemplateMap[name]; } - _builder.AppendLine($" {index++} => new global::System.Collections.Generic.KeyValuePair(\"{name}\", this._{p.Name}),"); + _builder.AppendLine($" {nestedIndentation}{index++} => new global::System.Collections.Generic.KeyValuePair(\"{name}\", this._{p.Name}),"); } - _builder.AppendLine($" {index++} => new global::System.Collections.Generic.KeyValuePair(\"{{OriginalFormat}}\", \"{ConvertEndOfLineAndQuotationCharactersToEscapeForm(lm.Message)}\"),"); + _builder.AppendLine($" {nestedIndentation}{index++} => new global::System.Collections.Generic.KeyValuePair(\"{{OriginalFormat}}\", \"{ConvertEndOfLineAndQuotationCharactersToEscapeForm(lm.Message)}\"),"); } private void GenCallbackArguments(LoggerMethod lm) @@ -321,7 +349,7 @@ namespace {lc.Namespace} _builder.Append(')'); } - private void GenLogMethod(LoggerMethod lm) + private void GenLogMethod(LoggerMethod lm, string nestedIndentation) { string level = GetLogLevel(lm); string extension = lm.IsExtensionMethod ? "this " : string.Empty; @@ -332,13 +360,13 @@ namespace {lc.Namespace} if (UseLoggerMessageDefine(lm)) { _builder.Append($@" - [{s_generatedCodeAttribute}] - private static readonly global::System.Action __{lm.Name}Callback = - global::Microsoft.Extensions.Logging.LoggerMessage.Define"); + _builder.Append($@"global::System.Exception?> __{lm.Name}Callback = + {nestedIndentation}global::Microsoft.Extensions.Logging.LoggerMessage.Define"); GenDefineTypes(lm, brackets: true); @@ -347,20 +375,20 @@ namespace {lc.Namespace} } _builder.Append($@" - [{s_generatedCodeAttribute}] - {lm.Modifiers} void {lm.Name}({extension}"); + {nestedIndentation}[{s_generatedCodeAttribute}] + {nestedIndentation}{lm.Modifiers} void {lm.Name}({extension}"); GenParameters(lm); _builder.Append($@") - {{ - if ({logger}.IsEnabled({level})) - {{"); + {nestedIndentation}{{ + {nestedIndentation}if ({logger}.IsEnabled({level})) + {nestedIndentation}{{"); if (UseLoggerMessageDefine(lm)) { _builder.Append($@" - __{lm.Name}Callback({logger}, "); + {nestedIndentation}__{lm.Name}Callback({logger}, "); GenCallbackArguments(lm); @@ -369,7 +397,7 @@ namespace {lc.Namespace} else { _builder.Append($@" - {logger}.Log( + {nestedIndentation}{logger}.Log( {level}, new global::Microsoft.Extensions.Logging.EventId({lm.EventId}, {eventName}), "); @@ -380,8 +408,8 @@ namespace {lc.Namespace} } _builder.Append($@" - }} - }}"); + {nestedIndentation}}} + {nestedIndentation}}}"); static string GetException(LoggerMethod lm) { diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs index 8542778..534249c 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs @@ -28,7 +28,7 @@ namespace Microsoft.Extensions.Logging.Generators } /// - /// Gets the set of logging classes containing methods to output. + /// Gets the set of logging classes or structs containing methods to output. /// public IReadOnlyList GetLogClasses(IEnumerable classes) { @@ -331,28 +331,23 @@ namespace Microsoft.Extensions.Logging.Generators if (lc == null) { // determine the namespace the class is declared in, if any - var ns = classDec.Parent as NamespaceDeclarationSyntax; - if (ns == null) + SyntaxNode? potentialNamespaceParent = classDec.Parent; + while (potentialNamespaceParent != null && potentialNamespaceParent is not NamespaceDeclarationSyntax) { - 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; - } + potentialNamespaceParent = potentialNamespaceParent.Parent; } - else + if (potentialNamespaceParent is NamespaceDeclarationSyntax namespaceParent) { - nspace = ns.Name.ToString(); + nspace = namespaceParent.Name.ToString(); while (true) { - ns = ns.Parent as NamespaceDeclarationSyntax; - if (ns == null) + namespaceParent = namespaceParent.Parent as NamespaceDeclarationSyntax; + if (namespaceParent == null) { break; } - nspace = $"{ns.Name}.{nspace}"; + nspace = $"{namespaceParent.Name}.{nspace}"; } } } @@ -361,11 +356,36 @@ namespace Microsoft.Extensions.Logging.Generators { lc ??= new LoggerClass { + Keyword = classDec.Keyword.ValueText, Namespace = nspace, Name = classDec.Identifier.ToString() + classDec.TypeParameterList, Constraints = classDec.ConstraintClauses.ToString(), + ParentClass = null, }; + LoggerClass currentLoggerClass = lc; + var parentLoggerClass = (classDec.Parent as TypeDeclarationSyntax); + + bool IsAllowedKind(SyntaxKind kind) => + kind == SyntaxKind.ClassDeclaration || + kind == SyntaxKind.StructDeclaration || + kind == SyntaxKind.RecordDeclaration; + + while (parentLoggerClass != null && IsAllowedKind(parentLoggerClass.Kind())) + { + currentLoggerClass.ParentClass = new LoggerClass + { + Keyword = parentLoggerClass.Keyword.ValueText, + Namespace = nspace, + Name = parentLoggerClass.Identifier.ToString() + parentLoggerClass.TypeParameterList, + Constraints = parentLoggerClass.ConstraintClauses.ToString(), + ParentClass = null, + }; + + currentLoggerClass = currentLoggerClass.ParentClass; + parentLoggerClass = (parentLoggerClass.Parent as TypeDeclarationSyntax); + } + lc.Methods.Add(lm); } } @@ -568,9 +588,11 @@ namespace Microsoft.Extensions.Logging.Generators internal class LoggerClass { public readonly List Methods = new (); + public string Keyword = string.Empty; public string Namespace = string.Empty; public string Name = string.Empty; public string Constraints = string.Empty; + public LoggerClass? ParentClass; } /// diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx index ed06151..66a9a1e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx @@ -123,9 +123,6 @@ Logging method parameter names cannot start with _ - - Logging class cannot be in nested types - Could not find a required type definition diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf index 980f5e2..7e5140b 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf index 3c5bd3f..c0b1d1b 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf index 3678d12..f18fd61 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf index aa1939b..ae9e608 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf index cf54d51..241484f 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf index 70ccaa7..3854417 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf index c7248aa..1fec30a 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf index 4752235..3bfdf3e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf index da1942b..4417c68 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf index ed2de8c..5263092 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf index 4b86ee0..539f7ec 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf index 87f8d9b..cbc17ee 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf index a34749c..297a39f 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf @@ -37,11 +37,6 @@ Logging methods cannot have a body - - Logging class cannot be in nested types - Logging class cannot be in nested types - - Logging methods cannot be generic Logging methods cannot be generic diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClass.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClass.generated.txt new file mode 100644 index 0000000..024e046 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClass.generated.txt @@ -0,0 +1,36 @@ +// +#nullable enable + +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses.NestedNamespace +{ + partial class MultiLevelNestedClass + { + partial struct NestedStruct + { + partial record NestedRecord + { + partial class NestedClassTestsExtensions where T1 : Class1 + { + partial class NestedMiddleParentClass + { + partial class Nested where T2 : Class2 + { + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + private static readonly global::System.Action __M9Callback = + global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(9, nameof(M9)), "M9", true); + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + public static partial void M9(global::Microsoft.Extensions.Logging.ILogger logger) + { + if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Debug)) + { + __M9Callback(logger, null); + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs index 7e0661d..c9180b7 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs @@ -346,6 +346,47 @@ namespace Microsoft.Extensions.Logging.Generators.Tests } [Fact] + public void NestedClassTests() + { + var logger = new MockLogger(); + + logger.Reset(); + NestedClassTestsExtensions.NestedMiddleParentClass.NestedClass.M8(logger); + Assert.Null(logger.LastException); + Assert.Equal("M8", logger.LastFormattedString); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + NonStaticNestedClassTestsExtensions.NonStaticNestedMiddleParentClass.NestedClass.M9(logger); + Assert.Null(logger.LastException); + Assert.Equal("M9", logger.LastFormattedString); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + NestedStruct.Logger.M10(logger); + Assert.Null(logger.LastException); + Assert.Equal("M10", logger.LastFormattedString); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + NestedRecord.Logger.M11(logger); + Assert.Null(logger.LastException); + Assert.Equal("M11", logger.LastFormattedString); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + MultiLevelNestedClass.NestedStruct.NestedRecord.Logger.M12(logger); + Assert.Null(logger.LastException); + Assert.Equal("M12", logger.LastFormattedString); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Equal(1, logger.CallCount); + } + + [Fact] public void TemplateTests() { var logger = new MockLogger(); diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs index d727420..433d601 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs @@ -80,6 +80,41 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses await VerifyAgainstBaselineUsingFile("TestWithDynamicLogLevel.generated.txt", testSourceCode); } + [Fact] + public async Task TestBaseline_TestWithNestedClass_Success() + { + string testSourceCode = @" +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + namespace NestedNamespace + { + public static partial class MultiLevelNestedClass + { + public partial struct NestedStruct + { + internal partial record NestedRecord(string Name, string Address) + { + internal static partial class NestedClassTestsExtensions where T1 : Class1 + { + internal static partial class NestedMiddleParentClass + { + internal static partial class Nested where T2 : Class2 + { + [LoggerMessage(EventId = 9, Level = LogLevel.Debug, Message = ""M9"")] + public static partial void M9(ILogger logger); + } + } + } + } + } + } + internal class Class1 { } + internal class Class2 { } + } +}"; + await VerifyAgainstBaselineUsingFile("TestWithNestedClass.generated.txt", testSourceCode); + } + private async Task VerifyAgainstBaselineUsingFile(string filename, string testSourceCode) { string[] expectedLines = await File.ReadAllLinesAsync(Path.Combine("Baselines", filename)).ConfigureAwait(false); diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs index bb158e9..4991e41 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs @@ -250,7 +250,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests } [Fact] - public async Task NestedType() + public async Task NestedTypeOK() { IReadOnlyList diagnostics = await RunGenerator(@" partial class C @@ -263,8 +263,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests } "); - Assert.Single(diagnostics); - Assert.Equal(DiagnosticDescriptors.LoggingMethodInNestedType.Id, diagnostics[0].Id); + Assert.Empty(diagnostics); } [Fact] diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/NestedClassTestsExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/NestedClassTestsExtensions.cs new file mode 100644 index 0000000..4b5b6cd --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/NestedClassTestsExtensions.cs @@ -0,0 +1,63 @@ +// 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 NestedClassTestsExtensions where T : ABC + { + internal static partial class NestedMiddleParentClass + { + internal static partial class NestedClass + { + [LoggerMessage(EventId = 8, Level = LogLevel.Debug, Message = "M8")] + public static partial void M8(ILogger logger); + } + } + } + + internal partial class NonStaticNestedClassTestsExtensions where T : ABC + { + internal partial class NonStaticNestedMiddleParentClass + { + internal static partial class NestedClass + { + [LoggerMessage(EventId = 9, Level = LogLevel.Debug, Message = "M9")] + public static partial void M9(ILogger logger); + } + } + } + public class ABC {} + + public partial struct NestedStruct + { + internal static partial class Logger + { + [LoggerMessage(EventId = 10, Level = LogLevel.Debug, Message = "M10")] + public static partial void M10(ILogger logger); + } + } + + public partial record NestedRecord(string Name, string Address) + { + internal static partial class Logger + { + [LoggerMessage(EventId = 11, Level = LogLevel.Debug, Message = "M11")] + public static partial void M11(ILogger logger); + } + } + + public static partial class MultiLevelNestedClass + { + public partial struct NestedStruct + { + internal partial record NestedRecord(string Name, string Address) + { + internal static partial class Logger + { + [LoggerMessage(EventId = 12, Level = LogLevel.Debug, Message = "M12")] + public static partial void M12(ILogger logger); + } + } + } + } +}