Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

namespace Microsoft.Extensions.Logging.Generators
{
Expand Down Expand Up @@ -181,7 +182,7 @@ private void GenStruct(LoggerMethod lm, string nestedIndentation)
string formatMethodEnd = formatMethodBegin.Length > 0 ? ")" : "";

_builder.Append($@"
{nestedIndentation}return {formatMethodBegin}$""{ConvertEndOfLineAndQuotationCharactersToEscapeForm(lm.Message)}""{formatMethodEnd};
{nestedIndentation}return {formatMethodBegin}${SymbolDisplay.FormatLiteral(lm.Message, quote: true)}{formatMethodEnd};
{nestedIndentation}}}
");
_builder.Append($@"
Expand Down Expand Up @@ -280,7 +281,7 @@ private void GenCases(LoggerMethod lm, string nestedIndentation)
_builder.AppendLine($" {nestedIndentation}{index++} => new global::System.Collections.Generic.KeyValuePair<string, object?>(\"{name}\", this.{NormalizeSpecialSymbol(p.CodeName)}),");
}

_builder.AppendLine($" {nestedIndentation}{index++} => new global::System.Collections.Generic.KeyValuePair<string, object?>(\"{{OriginalFormat}}\", \"{ConvertEndOfLineAndQuotationCharactersToEscapeForm(lm.Message)}\"),");
_builder.AppendLine($" {nestedIndentation}{index++} => new global::System.Collections.Generic.KeyValuePair<string, object?>(\"{{OriginalFormat}}\", {SymbolDisplay.FormatLiteral(lm.Message, quote: true)}),");
}

private void GenCallbackArguments(LoggerMethod lm)
Expand Down Expand Up @@ -406,7 +407,7 @@ private void GenLogMethod(LoggerMethod lm, string nestedIndentation)

GenDefineTypes(lm, brackets: true);

_builder.Append(@$"({level}, new global::Microsoft.Extensions.Logging.EventId({lm.EventId}, {eventName}), ""{ConvertEndOfLineAndQuotationCharactersToEscapeForm(lm.Message)}"", new global::Microsoft.Extensions.Logging.LogDefineOptions() {{ SkipEnabledCheck = true }});
_builder.Append(@$"({level}, new global::Microsoft.Extensions.Logging.EventId({lm.EventId}, {eventName}), {SymbolDisplay.FormatLiteral(lm.Message, quote: true)}, new global::Microsoft.Extensions.Logging.LogDefineOptions() {{ SkipEnabledCheck = true }});
");
}

Expand Down Expand Up @@ -576,55 +577,6 @@ public static string Enumerate(global::System.Collections.IEnumerable? enumerabl
}
}

private static string ConvertEndOfLineAndQuotationCharactersToEscapeForm(string s)
{
int index = 0;
while (index < s.Length)
{
if (s[index] is '\n' or '\r' or '"')
{
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();
}
/// <summary>
/// Checks if variableOrTemplateName contains a special symbol ('@') as starting char
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Exception?> __M0Callback =
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
public partial void M0()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Exception?> __M0Callback =
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
public partial void M0()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Exception?> __M0Callback =
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
public partial void M0()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Exception?> __LogACallback =
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(1, nameof(LogA)), "Message from ClassA", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(1, nameof(LogA)), "Message from ClassA", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
static partial void LogA(global::Microsoft.Extensions.Logging.ILogger logger)
Expand All @@ -25,7 +25,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Exception?> __LogBCallback =
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Information, new global::Microsoft.Extensions.Logging.EventId(2, nameof(LogB)), "Message from ClassB", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Information, new global::Microsoft.Extensions.Logging.EventId(2, nameof(LogB)), "Message from ClassB", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
static partial void LogB(global::Microsoft.Extensions.Logging.ILogger logger)
Expand All @@ -43,7 +43,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Exception?> __LogCCallback =
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Warning, new global::Microsoft.Extensions.Logging.EventId(3, nameof(LogC)), "Message from ClassC", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Warning, new global::Microsoft.Extensions.Logging.EventId(3, nameof(LogC)), "Message from ClassC", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
static partial void LogC(global::Microsoft.Extensions.Logging.ILogger logger)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses.NestedNamesp
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Exception?> __M9Callback =
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(9, nameof(M9)), "M9", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(9, nameof(M9)), "M9", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
public static partial void M9(global::Microsoft.Extensions.Logging.ILogger logger)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, A, B, C, global::System.Exception?> __M0Callback =
global::Microsoft.Extensions.Logging.LoggerMessage.Define<A, B, C>(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(42, nameof(M0)), "a = {a}; b = {b}; c = {c}", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
global::Microsoft.Extensions.Logging.LoggerMessage.Define<A, B, C>(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(42, nameof(M0)), "a = {a}; b = {b}; c = {c}", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
public static partial void M0(global::Microsoft.Extensions.Logging.ILogger logger, A a, B b, C c)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Exception?> __M0Callback =
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Information, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "Message: When using SkipEnabledCheck, the generated code skips logger.IsEnabled(logLevel) check before calling log. To be used when consumer has already guarded logger method in an IsEnabled check.", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Information, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "Message: When using SkipEnabledCheck, the generated code skips logger.IsEnabled(logLevel) check before calling log. To be used when consumer has already guarded logger method in an IsEnabled check.", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
public static partial void M0(global::Microsoft.Extensions.Logging.ILogger logger)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Int32, global::System.Collections.Generic.IEnumerable<global::System.Int32>, global::System.Exception?> __M0Callback =
global::Microsoft.Extensions.Logging.LoggerMessage.Define<global::System.Int32, global::System.Collections.Generic.IEnumerable<global::System.Int32>>(global::Microsoft.Extensions.Logging.LogLevel.Error, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0 {a1} {a2}", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
global::Microsoft.Extensions.Logging.LoggerMessage.Define<global::System.Int32, global::System.Collections.Generic.IEnumerable<global::System.Int32>>(global::Microsoft.Extensions.Logging.LogLevel.Error, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0 {a1} {a2}", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
public static partial void M0(global::Microsoft.Extensions.Logging.ILogger logger, global::System.Int32 a1, global::System.Collections.Generic.IEnumerable<global::System.Int32> a2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,58 @@ public void GenericTypeParameterAttributesAreRetained()
Assert.NotNull(type.GenericTypeParameters[1].GetCustomAttribute<TestClasses.BarAttribute>());
}

[Theory]
[InlineData(@"Foo \\ bar: {foo}", null)]
[InlineData(@"Foo \\\\ bar: {foo}", null)]
[InlineData(@"Foo \"" bar: {foo}", null)]
[InlineData(@"Foo \x22 bar: {foo}", @"Foo \"" bar: {foo}")]
[InlineData(@"Foo \u0022 bar: {foo}", @"Foo \"" bar: {foo}")]
[InlineData(@"Foo \r bar: {foo}", null)]
[InlineData(@"Foo \x0d bar: {foo}", @"Foo \r bar: {foo}")]
[InlineData(@"Foo \u000d bar: {foo}", @"Foo \r bar: {foo}")]
[InlineData(@"Foo \n bar: {foo}", null)]
[InlineData(@"Foo \x0a bar: {foo}", @"Foo \n bar: {foo}")]
[InlineData(@"Foo \u000a bar: {foo}", @"Foo \n bar: {foo}")]
[InlineData(@"Foo \0 bar: {foo}", null)]
[InlineData(@"Foo \x00 bar: {foo}", @"Foo \0 bar: {foo}")]
[InlineData(@"Foo \u0000 bar: {foo}", @"Foo \0 bar: {foo}")]
[InlineData(@"Foo \x1f bar: {foo}", @"Foo \u001f bar: {foo}")]
[InlineData(@"Foo \u001f bar: {foo}", null)]
public async Task EmittedMessageIsWellFormed(string message, string? expectedMessage)
{
var code =
$$"""
namespace Test
{
using Microsoft.Extensions.Logging;

partial class C
{
[LoggerMessage(EventId = 5230, Level = LogLevel.Information, Message = "{{message}}")]
static partial void Test(ILogger logger, string foo);
}
}
""";

var (diagnostics, generatedSources) = await RoslynTestUtils
.RunGenerator(
new LoggerMessageGenerator(),
new[] { typeof(ILogger).Assembly, typeof(LoggerMessageAttribute).Assembly },
new[] { code },
includeBaseReferences: true)
.ConfigureAwait(false);

Assert.Empty(diagnostics);
Assert.Single(generatedSources);

var generatedSource = generatedSources[0];
var src = generatedSource.SourceText.ToString();
Assert.Contains($"\"{expectedMessage ?? message}\"", src);

var generatedSourceDiagnostics = generatedSource.SyntaxTree.GetDiagnostics();
Assert.Empty(generatedSourceDiagnostics);
}

private async Task VerifyAgainstBaselineUsingFile(string filename, string testSourceCode)
{
string baseline = LineEndingsHelper.Normalize(File.ReadAllText(Path.Combine("Baselines", filename)));
Expand Down
Loading