Open
Description
Description
The code below fails to compile depending on the order of the placeholders in the template. It only happens when a C# keyword with an @ prefix is included.
Reproduction Steps
private readonly ILogger _logger = new LoggerFactory().CreateLogger("SomeNamespace");
static void Main(string[] args) { }
[LoggerMessage(eventId: 1, LogLevel.Information, "Resource: {resource}. Namespace: {namespace}.")]
partial void LogEvent(string @namespace, string resource);
The above generates the following invalid code (see unescaped variable namespace
):
public override string ToString()
{
var resource = this._resource;
var namespace = this.@namespace;
return $"Resource: {resource}. Namespace: {namespace}.";
}
Expected behavior
The generator should generate valid escaped code to reference the c# keywords.
Actual behavior
Some of the warnings and errors include:
Warning S3251: Supply an implementation for this partial method.
error CS0759: No defining declaration found for implementing declaration of partial method '<invalid-global-code>.LogEvent(string, string)'
error CS0751: A partial method must be declared within a partial type
error CS0116: A namespace cannot directly contain members such as fields, methods or statements
error CS0246: The type or namespace name 'namespace' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name '__LogEventStruct' could not be found (are you missing a using directive or an assembly reference?)
error CS0540: '<invalid-global-code>.IEnumerable.GetEnumerator()': containing type does not implement interface 'IEnumerable'
error CS0548: '<invalid-global-code>.this[namespace]': property or indexer must have at least one accessor
error CS0535: 'Program.__LogEventStruct' does not implement interface member 'IReadOnlyList<KeyValuePair<string, object?>>.this[int]'
error CS0535: 'Program.__LogEventStruct' does not implement interface member 'IReadOnlyCollection<KeyValuePair<string, object?>>.Count'
error CS0535: 'Program.__LogEventStruct' does not implement interface member 'IEnumerable<KeyValuePair<string, object?>>.GetEnumerator()'
error CS0535: 'Program.__LogEventStruct' does not implement interface member 'IEnumerable.GetEnumerator()'
Regression?
No response
Known Workarounds
The order of the placeholders should match the order of the parameters. The following compiles and works fine:
[LoggerMessage(eventId: 1, LogLevel.Information, "Namespace: {namespace}. Resource: {resource}.")]
partial void LogEvent(string @namespace, string resource);
If the placeholder for the C# keyword uses PascalCase as recommended by CA1727, it also works fine:
[LoggerMessage(eventId: 1, LogLevel.Information, "Resource: {resource}. Namespace: {Namespace}.")]
partial void LogEvent(string @namespace, string resource);
Configuration
Reproduced with:
- .NET 7
- Microsoft.Extensions.Logging
7.0.0
and8.0.0
- Microsoft.Extensions.Logging.Abstractions
7.0.0
,7.0.1
and8.0.0
Other information
No response