From 8521541d63e59bfdd7d9d27295a42e3e2b613857 Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Sun, 5 Feb 2023 16:19:43 -0300 Subject: [PATCH] diagnostic to detect malformed format strings in lsg template message (#81503) fix https://github.com/dotnet/runtime/issues/52226 --- docs/project/list-of-diagnostics.md | 2 +- .../gen/DiagnosticDescriptors.cs | 2 +- .../gen/LoggerMessageGenerator.Parser.cs | 125 ++++++++++++------ .../gen/Resources/Strings.resx | 7 +- .../gen/Resources/xlf/Strings.cs.xlf | 9 +- .../gen/Resources/xlf/Strings.de.xlf | 9 +- .../gen/Resources/xlf/Strings.es.xlf | 9 +- .../gen/Resources/xlf/Strings.fr.xlf | 9 +- .../gen/Resources/xlf/Strings.it.xlf | 9 +- .../gen/Resources/xlf/Strings.ja.xlf | 9 +- .../gen/Resources/xlf/Strings.ko.xlf | 9 +- .../gen/Resources/xlf/Strings.pl.xlf | 9 +- .../gen/Resources/xlf/Strings.pt-BR.xlf | 77 ++++++----- .../gen/Resources/xlf/Strings.ru.xlf | 73 +++++----- .../gen/Resources/xlf/Strings.tr.xlf | 9 +- .../gen/Resources/xlf/Strings.zh-Hans.xlf | 69 +++++----- .../gen/Resources/xlf/Strings.zh-Hant.xlf | 9 +- .../LoggerMessageGeneratorParserTests.cs | 101 ++++++++------ 18 files changed, 337 insertions(+), 209 deletions(-) diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md index 9de73544657bd..169bd9eab0462 100644 --- a/docs/project/list-of-diagnostics.md +++ b/docs/project/list-of-diagnostics.md @@ -133,7 +133,7 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL | __`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) | +| __`SYSLIB1022`__ | Logging method contains malformed format strings | | __`SYSLIB1023`__ | Generating more than 6 arguments is not supported | | __`SYSLIB1024`__ | Argument is using the unsupported out parameter modifier | | __`SYSLIB1025`__ | Multiple logging methods cannot use the same event name within a class | diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs index 1c732cc5b29b1..5192b75f1f1f9 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs @@ -170,7 +170,7 @@ public static class DiagnosticDescriptors public static DiagnosticDescriptor MalformedFormatStrings { get; } = new DiagnosticDescriptor( id: "SYSLIB1022", - title: new LocalizableResourceString(nameof(SR.MalformedFormatStringsMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)), + title: new LocalizableResourceString(nameof(SR.MalformedFormatStringsTitle), 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, 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 a04ad02676ad1..ecbc1d78b09f2 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs @@ -204,9 +204,15 @@ public IReadOnlyList GetLogClasses(IEnumerable /// Finds the template arguments contained in the message string. /// - private static void ExtractTemplates(string? message, IDictionary templateMap, List templateList) + /// A value indicating whether the extraction was successful. + private static bool ExtractTemplates(string? message, IDictionary templateMap, List templateList) { if (string.IsNullOrEmpty(message)) { - return; + return true; } int scanIndex = 0; - int endIndex = message!.Length; + int endIndex = message.Length; + bool success = true; while (scanIndex < endIndex) { int openBraceIndex = FindBraceIndex(message, '{', scanIndex, endIndex); - int closeBraceIndex = FindBraceIndex(message, '}', openBraceIndex, endIndex); - if (closeBraceIndex == endIndex) + if (openBraceIndex == -2) // found '}' instead of '{' { - scanIndex = endIndex; + success = false; + break; } - else + else if (openBraceIndex == -1) // scanned the string and didn't find any remaining '{' or '}' + { + break; + } + + int closeBraceIndex = FindBraceIndex(message, '}', openBraceIndex + 1, endIndex); + + if (closeBraceIndex <= -1) // unclosed '{' { - // Format item syntax : { index[,alignment][ :formatString] }. - int formatDelimiterIndex = FindIndexOfAny(message, _formatDelimiters, openBraceIndex, closeBraceIndex); + success = false; + break; + } + + // Format item syntax : { index[,alignment][ :formatString] }. + int formatDelimiterIndex = FindIndexOfAny(message, _formatDelimiters, openBraceIndex, closeBraceIndex); + string templateName = message.Substring(openBraceIndex + 1, formatDelimiterIndex - openBraceIndex - 1); - string templateName = message.Substring(openBraceIndex + 1, formatDelimiterIndex - openBraceIndex - 1); - templateMap[templateName] = templateName; - templateList.Add(templateName); - scanIndex = closeBraceIndex + 1; + if (string.IsNullOrWhiteSpace(templateName)) // braces with no named argument, such as {} and { } + { + success = false; + break; } + + templateMap[templateName] = templateName; + templateList.Add(templateName); + + scanIndex = closeBraceIndex + 1; } + + return success; } - private static int FindBraceIndex(string message, char brace, int startIndex, int endIndex) + /// + /// Searches for the next brace index in the message. + /// + /// The search skips any sequences of {{ or }}. + /// {{prefix{{{Argument}}}suffix}} + /// The zero-based index position of the first occurrence of the searched brace; -1 if the searched brace was not found; -2 if the wrong brace was found. + private static int FindBraceIndex(string message, char searchedBrace, int startIndex, int endIndex) { - // Example: {{prefix{{{Argument}}}suffix}}. - int braceIndex = endIndex; + Debug.Assert(searchedBrace is '{' or '}'); + + int braceIndex = -1; int scanIndex = startIndex; - int braceOccurrenceCount = 0; while (scanIndex < endIndex) { - if (braceOccurrenceCount > 0 && message[scanIndex] != brace) + char current = message[scanIndex]; + + if (current is '{' or '}') { - if (braceOccurrenceCount % 2 == 0) + char currentBrace = current; + + int scanIndexBeforeSkip = scanIndex; + while (current == currentBrace && ++scanIndex < endIndex) { - // Even number of '{' or '}' found. Proceed search with next occurrence of '{' or '}'. - braceOccurrenceCount = 0; - braceIndex = endIndex; + current = message[scanIndex]; } - else + + int bracesCount = scanIndex - scanIndexBeforeSkip; + if (bracesCount % 2 != 0) // if it is an even number of braces, just skip them, otherwise, we found an unescaped brace { - // An unescaped '{' or '}' found. + if (currentBrace == searchedBrace) + { + if (currentBrace == '{') + { + braceIndex = scanIndex - 1; // For '{' pick the last occurrence. + } + else + { + braceIndex = scanIndexBeforeSkip; // For '}' pick the first occurrence. + } + } + else + { + braceIndex = -2; // wrong brace found + } + break; } } - else if (message[scanIndex] == brace) + else { - if (brace == '}') - { - if (braceOccurrenceCount == 0) - { - // For '}' pick the first occurrence. - braceIndex = scanIndex; - } - } - else - { - // For '{' pick the last occurrence. - braceIndex = scanIndex; - } - - braceOccurrenceCount++; + scanIndex++; } - - scanIndex++; } return braceIndex; 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 12f892d8d701b..529263fda731f 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx @@ -211,7 +211,7 @@ Can't have the same template with different casing - Can't have malformed format strings (like dangling {, etc) + Logging method '{0}' contains malformed format strings Generating more than 6 arguments is not supported @@ -228,4 +228,7 @@ Multiple logging methods should not use the same event name within a class - + + Logging method contains malformed format strings + + \ No newline at end of file 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 416fc1c684315..36c6ba36f4f98 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 @@ -68,8 +68,13 @@ - Can't have malformed format strings (like dangling {, etc) - Nemůže mít chybně formátované řetězce (třeba neuzavřené závorky { atd.). + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings 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 5fdfb17d4c637..14ace407cd200 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 @@ -68,8 +68,13 @@ - Can't have malformed format strings (like dangling {, etc) - Nicht wohlgeformte Formatzeichenfolgen (beispielsweise mit überzähligen geschweiften Klammern) sind unzulässig. + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings 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 508a09d9e935b..b6c52c90ca889 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 @@ -68,8 +68,13 @@ - Can't have malformed format strings (like dangling {, etc) - No puede tener cadenas con formato incorrecto (como { final, etc.) + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings 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 58fa9edb87be3..b0b2006e5013b 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 @@ -68,8 +68,13 @@ - Can't have malformed format strings (like dangling {, etc) - Chaînes de format incorrect (par exemple { non fermée, etc.) + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings 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 dc9403d78700a..9c8da0cba4f9d 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 @@ -68,8 +68,13 @@ - Can't have malformed format strings (like dangling {, etc) - Impossibile avere stringhe di formato non valido (ad esempio, { tralasciato e così via) + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings 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 c68bf6bb5c054..304d24fdf1129 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 @@ -68,8 +68,13 @@ - Can't have malformed format strings (like dangling {, etc) - (dangling {など) 誤った形式の文字列を持つことはできません + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings 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 0a9542f3363d0..46b823d0e07b9 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 @@ -68,8 +68,13 @@ - Can't have malformed format strings (like dangling {, etc) - 잘못된 형식의 문자열(예: 짝이 맞지 않는 중괄호({))은 사용할 수 없음 + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings 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 f74d1917ab03a..e12d5fbc8612a 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 @@ -68,8 +68,13 @@ - Can't have malformed format strings (like dangling {, etc) - Nie może zawierać źle sformułowanego formatu ciągów (takich jak zawieszonego znaku „{”, itp.) + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings 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 df317c992d286..5cf0dd356529a 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 @@ -4,177 +4,182 @@ Argument '{0}' is not referenced from the logging message - O argumento '{0}' não é referenciado na mensagem de registro em log + Argument '{0}' is not referenced from the logging message Argument is not referenced from the logging message - O argumento não é referenciado na mensagem de registro em log + Argument is not referenced from the logging message Generating more than 6 arguments is not supported - A geração de mais de 6 argumentos não é suportada + Generating more than 6 arguments is not supported Can't have the same template with different casing - Não é possível ter o mesmo modelo com diferenças entre maiúsculas e minúsculas. + Can't have the same template with different casing Logging method names cannot start with _ - Os nomes dos métodos de registro em log não podem começar com _ + Logging method names cannot start with _ Logging method parameter names cannot start with _ - Os nomes dos parâmetros do método de registro em log não podem começar com _ + Logging method parameter names cannot start with _ Argument '{0}' is using the unsupported out parameter modifier - O argumento '{0}' está usando o modificador de parâmetro out sem suporte + Argument '{0}' is using the unsupported out parameter modifier Argument is using the unsupported out parameter modifier - O argumento está usando o modificador de parâmetro out sem suporte + Argument is using the unsupported out parameter modifier Logging methods cannot have a body - Os métodos de registro em log não podem ter um corpo + Logging methods cannot have a body Logging methods cannot be generic - Os métodos de registro em log não podem ser genéricos + Logging methods cannot be generic Logging methods must be partial - Os métodos de registro em log devem ser parciais + Logging methods must be partial Logging methods must return void - Os métodos de registro em log devem retornar nulos + Logging methods must return void Logging methods must be static - Os métodos de registro em log devem ser estáticos + Logging methods must be static - Can't have malformed format strings (like dangling {, etc) - Não pode ter cadeia de caracteres de formato malformadas (como final {, etc) + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method - Um valor LogLevel deve ser fornecido no atributo LoggerMessage ou como um parâmetro para o método de registro em log + A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface - Um dos argumentos para um método de log estático '{0}' deve implementar a interface Microsoft.Extensions.Logging.ILogger + One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface {Locked="Microsoft.Extensions.Logging.ILogger"} One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface - Um dos argumentos para um método de log estático deve implementar a interface Microsoft.Extensions.Logging.ILogger + One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface {Locked="Microsoft.Extensions.Logging.ILogger"} Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0} - Não foi possível encontrar um campo do tipo Microsoft.Extensions.Logging.ILogger na classe {0} + Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0} {Locked="Microsoft.Extensions.Logging.ILogger"} Couldn't find a field of type Microsoft.Extensions.Logging.ILogger - Não foi possível encontrar um campo do tipo Microsoft.Extensions.Logging.ILogger + Couldn't find a field of type Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} Could not find definition for type {0} - Não foi possível encontrar a definição para o tipo {0} + Could not find definition for type {0} Could not find a required type definition - Não foi possível encontrar uma definição de tipo necessária + Could not find a required type definition Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0} - Múltiplos campos do tipo Microsoft.Extensions.Logging.ILogger encontrados na classe {0} + Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0} {Locked="Microsoft.Extensions.Logging.ILogger"} Found multiple fields of type Microsoft.Extensions.Logging.ILogger - Múltiplos campos encontrados do tipo Microsoft.Extensions.Logging.ILogger + Found multiple fields of type Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. - Remova o qualificador redundante (Info:, Aviso:, Erro:, etc) da mensagem de log, pois está implícito no nível de log especificado. + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Redundant qualifier in logging message - Qualificador redundante na mensagem de registro de log + Redundant qualifier in logging message Don't include exception parameters as templates in the logging message - Não inclua parâmetros de exceção como modelos na mensagem de registro em log + Don't include exception parameters as templates in the logging message Don't include a template for {0} in the logging message since it is implicitly taken care of - Não inclua um modelo para {0} na mensagem de registro em log, pois isso é implicitamente atendido + Don't include a template for {0} in the logging message since it is implicitly taken care of Don't include log level parameters as templates in the logging message - Não inclua parâmetros de nível de registro como modelos na mensagem de registro de log + Don't include log level parameters as templates in the logging message Don't include logger parameters as templates in the logging message - Não inclua parâmetros de agente como modelos na mensagem de registro em log + Don't include logger parameters as templates in the logging message Multiple logging methods are using event id {0} in class {1} - Múltiplos métodos de registro em log estão usando a id de evento {0} na classe {1} + Multiple logging methods are using event id {0} in class {1} Multiple logging methods cannot use the same event id within a class - Múltiplos métodos de registro em log não podem usar o mesmo id de evento dentro de uma classe + Multiple logging methods cannot use the same event id within a class Multiple logging methods are using event name {0} in class {1} - Múltiplos métodos de registro em log estão usando o nome de evento {0} na classe {1} + Multiple logging methods are using event name {0} in class {1} Multiple logging methods should not use the same event name within a class - Múltiplos métodos de registro em log não devem usar o mesmo nome de evento dentro de uma classe + Multiple logging methods should not use the same event name within a class Template '{0}' is not provided as argument to the logging method - O modelo '{0}' não é fornecido como argumento para o método de registro + Template '{0}' is not provided as argument to the logging method Logging template has no corresponding method argument - O modelo de registro em log não tem nenhum argumento de método correspondente + Logging template has no corresponding method argument 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 b4c4c4ad22e7b..7b0c9be5730af 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 @@ -4,157 +4,162 @@ Argument '{0}' is not referenced from the logging message - В сообщении ведения журнала нет ссылки на аргумент "{0}" + Argument '{0}' is not referenced from the logging message Argument is not referenced from the logging message - В сообщении ведения журнала нет ссылки на аргумент + Argument is not referenced from the logging message Generating more than 6 arguments is not supported - Формирование более 6 аргументов не поддерживается + Generating more than 6 arguments is not supported Can't have the same template with different casing - Невозможно использовать шаблон с таким же именем в другом регистре + Can't have the same template with different casing Logging method names cannot start with _ - Имена методов ведения журнала не могут начинаться с символа "_" + Logging method names cannot start with _ Logging method parameter names cannot start with _ - Имена параметров метода ведения журнала не могут начинаться с символа "_" + Logging method parameter names cannot start with _ Argument '{0}' is using the unsupported out parameter modifier - Аргумент "{0}" использует неподдерживаемый модификатор выходного параметра + Argument '{0}' is using the unsupported out parameter modifier Argument is using the unsupported out parameter modifier - Аргумент использует неподдерживаемый модификатор выходного параметра + Argument is using the unsupported out parameter modifier Logging methods cannot have a body - У методов ведения журнала не может быть текста + Logging methods cannot have a body Logging methods cannot be generic - Методы ведения журнала не могут быть универсальными + Logging methods cannot be generic Logging methods must be partial - Методы ведения журнала должны быть частичными + Logging methods must be partial Logging methods must return void - Методы ведения журнала должны возвращать значение void + Logging methods must return void Logging methods must be static - Методы ведения журнала должны быть статическими + Logging methods must be static - Can't have malformed format strings (like dangling {, etc) - Для строк формата не допускается неправильный формат (висячие символы "{" и т. п.) + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method - Значение LogLevel должно быть указано в атрибуте LoggerMessage или в качестве параметра метода ведения журнала + A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface - Один из аргументов статического метода ведения журнала "{0}" должен реализовывать интерфейс Microsoft.Extensions.Logging.ILogger + One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface {Locked="Microsoft.Extensions.Logging.ILogger"} One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface - Один из аргументов статического метода ведения журнала должен реализовывать интерфейс Microsoft.Extensions.Logging.ILogger + One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface {Locked="Microsoft.Extensions.Logging.ILogger"} Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0} - В классе {0} не найдены поля типа Microsoft.Extensions.Logging.ILogger + Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0} {Locked="Microsoft.Extensions.Logging.ILogger"} Couldn't find a field of type Microsoft.Extensions.Logging.ILogger - Не удалось найти поле типа Microsoft.Extensions.Logging.ILogger + Couldn't find a field of type Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} Could not find definition for type {0} - Не найдено определение для типа {0} + Could not find definition for type {0} Could not find a required type definition - Не найдено требуемое определение типа + Could not find a required type definition Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0} - В классе {0} обнаружено несколько полей типа Microsoft.Extensions.Logging.ILogger + Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0} {Locked="Microsoft.Extensions.Logging.ILogger"} Found multiple fields of type Microsoft.Extensions.Logging.ILogger - Обнаружено несколько полей типа Microsoft.Extensions.Logging.ILogger + Found multiple fields of type Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. - Удалите избыточный квалификатор (Info:, Warning:, Error:, и т. п.) из сообщения журнала, поскольку квалификатор подразумевается на указанном уровне ведения журнала. + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Redundant qualifier in logging message - Избыточный квалификатор в сообщении журнала + Redundant qualifier in logging message Don't include exception parameters as templates in the logging message - Не включайте параметры исключений в качестве шаблонов в сообщение ведения журнала + Don't include exception parameters as templates in the logging message Don't include a template for {0} in the logging message since it is implicitly taken care of - Не включайте шаблон для {0} в сообщение ведения журнала, поскольку он используется неявным образом + Don't include a template for {0} in the logging message since it is implicitly taken care of Don't include log level parameters as templates in the logging message - Не включайте параметры уровня журнала в качестве шаблонов в сообщение ведения журнала + Don't include log level parameters as templates in the logging message Don't include logger parameters as templates in the logging message - Не включайте параметры средства ведения журнала в качестве шаблонов в сообщение ведения журнала + Don't include logger parameters as templates in the logging message Multiple logging methods are using event id {0} in class {1} - Несколько методов ведения журнала используют идентификатор события {0} в классе {1} + Multiple logging methods are using event id {0} in class {1} Multiple logging methods cannot use the same event id within a class - Несколько методов ведения журнала не могут использовать одинаковый ИД события в пределах класса + Multiple logging methods cannot use the same event id within a class @@ -169,12 +174,12 @@ Template '{0}' is not provided as argument to the logging method - Шаблон "{0}" не указан в качестве аргумента для метода ведения журнала + Template '{0}' is not provided as argument to the logging method Logging template has no corresponding method argument - У шаблона журнала нет соответствующего аргумента метода + Logging template has no corresponding method argument 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 0e8b2fbd796dc..b7b86daf11298 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 @@ -68,8 +68,13 @@ - Can't have malformed format strings (like dangling {, etc) - Hatalı biçimlendirilmiş biçim dizeleri (aykırı { vb. gibi) içeremez + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings 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 da8b1b4bc5e33..28f6073d59ca0 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 @@ -4,32 +4,32 @@ Argument '{0}' is not referenced from the logging message - 未从日志记录消息中引用参数“{0}” + Argument '{0}' is not referenced from the logging message Argument is not referenced from the logging message - 未从日志记录消息中引用参数 + Argument is not referenced from the logging message Generating more than 6 arguments is not supported - 不支持生成 6 个以上的参数 + Generating more than 6 arguments is not supported Can't have the same template with different casing - 不能有大小写不同的相同模板 + Can't have the same template with different casing Logging method names cannot start with _ - 日志记录方法名称不能以 _ 开头 + Logging method names cannot start with _ Logging method parameter names cannot start with _ - 日志记录方法参数名称不能以 _ 开头 + Logging method parameter names cannot start with _ @@ -44,117 +44,122 @@ Logging methods cannot have a body - 日志记录方法不能有正文 + Logging methods cannot have a body Logging methods cannot be generic - 日志记录方法不能为泛型方法 + Logging methods cannot be generic Logging methods must be partial - 日志记录方法必须为分部方法 + Logging methods must be partial Logging methods must return void - 日志记录方法必须返回 void + Logging methods must return void Logging methods must be static - 日志记录方法必须为静态方法 + Logging methods must be static - Can't have malformed format strings (like dangling {, etc) - 不能有格式错误的格式字符串(例如悬空 { 等) + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method - 必须在 LoggerMessage 属性中提供 LogLevel 值或将其用作日志记录方法的参数 + A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface - 静态日志记录方法“{0}”的参数之一必须实施 Microsoft.Extensions.Logging.ILogger 接口 + One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface {Locked="Microsoft.Extensions.Logging.ILogger"} One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface - 静态日志记录方法的参数之一必须实现 Microsoft.Extensions.Logging.ILogger 接口 + One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface {Locked="Microsoft.Extensions.Logging.ILogger"} Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0} - 在类 {0} 中找不到 Microsoft.Extensions.Logging.ILogger 类型的字段 + Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0} {Locked="Microsoft.Extensions.Logging.ILogger"} Couldn't find a field of type Microsoft.Extensions.Logging.ILogger - 找不到 Microsoft.Extensions.Logging.ILogger 类型的字段。 + Couldn't find a field of type Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} Could not find definition for type {0} - 找不到类型 {0} 的定义 + Could not find definition for type {0} Could not find a required type definition - 找不到所需的类型定义 + Could not find a required type definition Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0} - 在类 {0} 中找到多个 Microsoft.Extensions.Logging.ILogger 类型的字段 + Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0} {Locked="Microsoft.Extensions.Logging.ILogger"} Found multiple fields of type Microsoft.Extensions.Logging.ILogger - 找到 Microsoft.Extensions.Logging.ILogger 类型的多个字段 + Found multiple fields of type Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. - 从日志记录消息中删除冗余限定符(信息:、警告:、错误: 等),因为其在指定的日志级别中为隐式内容。 + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Redundant qualifier in logging message - 日志消息消息中的冗余限定符 + Redundant qualifier in logging message Don't include exception parameters as templates in the logging message - 不要将异常参数作为模板包含在日志记录消息中 + Don't include exception parameters as templates in the logging message Don't include a template for {0} in the logging message since it is implicitly taken care of - 不要将 {0} 的模板包含在日志记录消息中,因为其被隐式处理 + Don't include a template for {0} in the logging message since it is implicitly taken care of Don't include log level parameters as templates in the logging message - 不要将日志级别参数作为模板包含在日志记录消息中 + Don't include log level parameters as templates in the logging message Don't include logger parameters as templates in the logging message - 不要将记录器参数作为模板包含在日志记录消息中 + Don't include logger parameters as templates in the logging message Multiple logging methods are using event id {0} in class {1} - 多个日志记录方法正在类 {1} 中使用事件 ID {0} + Multiple logging methods are using event id {0} in class {1} Multiple logging methods cannot use the same event id within a class - 多个日志记录方法不能在类中使用相同的事件 ID + Multiple logging methods cannot use the same event id within a class @@ -169,12 +174,12 @@ Template '{0}' is not provided as argument to the logging method - 未将模板“{0}”作为参数提供给日志记录方法 + Template '{0}' is not provided as argument to the logging method Logging template has no corresponding method argument - 日志记录模板无相应的方法参数 + Logging template has no corresponding method argument 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 c3dbe28ddb3a9..96b8c2d72b672 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 @@ -68,8 +68,13 @@ - Can't have malformed format strings (like dangling {, etc) - 不能有格式錯誤的格式字串 (例如懸空 {, 等等) + Logging method '{0}' contains malformed format strings + Logging method '{0}' contains malformed format strings + + + + Logging method contains malformed format strings + Logging method contains malformed format strings 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 564444c32ea2a..9d80c884bf2fa 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 @@ -325,40 +325,6 @@ partial class C Assert.Empty(diagnostics); } -#if false - // TODO: can't have the same template with different casing - [Fact] - public async Task InconsistentTemplateCasing() - { - IReadOnlyList 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 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() { @@ -699,16 +665,16 @@ partial class C } [Fact] - public async Task Templates() + public async Task MalformedFormatString() { IReadOnlyList diagnostics = await RunGenerator(@" partial class C { - [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = ""M1"")] + [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = ""M1 {A} M1 { 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 = 2, Level = LogLevel.Debug, Message = ""M2 {A} M2 } M2"")] + static partial void M2(ILogger logger); [LoggerMessage(EventId = 3, Level = LogLevel.Debug, Message = ""M3 {arg1"")] static partial void M3(ILogger logger); @@ -722,8 +688,65 @@ partial class C [LoggerMessage(EventId = 6, Level = LogLevel.Debug, Message = ""}M6 "")] static partial void M6(ILogger logger); - [LoggerMessage(EventId = 7, Level = LogLevel.Debug, Message = ""M7 {{arg1}}"")] + [LoggerMessage(EventId = 7, Level = LogLevel.Debug, Message = ""{M7{"")] + static partial void M7(ILogger logger); + + [LoggerMessage(EventId = 8, Level = LogLevel.Debug, Message = ""{{{arg1 M8"")] + static partial void M8(ILogger logger); + + [LoggerMessage(EventId = 9, Level = LogLevel.Debug, Message = ""arg1}}} M9"")] + static partial void M9(ILogger logger); + + [LoggerMessage(EventId = 10, Level = LogLevel.Debug, Message = ""{} M10"")] + static partial void M10(ILogger logger); + + [LoggerMessage(EventId = 11, Level = LogLevel.Debug, Message = ""{ } M11"")] + static partial void M11(ILogger logger); + } + "); + + Assert.Equal(11, diagnostics.Count); + foreach (var diagnostic in diagnostics) + { + Assert.Equal(DiagnosticDescriptors.MalformedFormatStrings.Id, diagnostic.Id); + } + } + + [Fact] + public async Task ValidTemplates() + { + IReadOnlyList diagnostics = await RunGenerator(@" + partial class C + { + [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = """")] + static partial void M1(ILogger logger); + + [LoggerMessage(EventId = 2, Level = LogLevel.Debug, Message = ""M2"")] + static partial void M2(ILogger logger); + + [LoggerMessage(EventId = 3, Level = LogLevel.Debug, Message = ""{arg1}"")] + static partial void M3(ILogger logger, int arg1); + + [LoggerMessage(EventId = 4, Level = LogLevel.Debug, Message = ""M4 {arg1}"")] + static partial void M4(ILogger logger, int arg1); + + [LoggerMessage(EventId = 5, Level = LogLevel.Debug, Message = ""{arg1} M5"")] + static partial void M5(ILogger logger, int arg1); + + [LoggerMessage(EventId = 6, Level = LogLevel.Debug, Message = ""M6{arg1}M6{arg2}M6"")] + static partial void M6(ILogger logger, string arg1, string arg2); + + [LoggerMessage(EventId = 7, Level = LogLevel.Debug, Message = ""M7 {{const}}"")] static partial void M7(ILogger logger); + + [LoggerMessage(EventId = 8, Level = LogLevel.Debug, Message = ""{{prefix{{{arg1}}}suffix}}"")] + static partial void M8(ILogger logger, string arg1); + + [LoggerMessage(EventId = 9, Level = LogLevel.Debug, Message = ""prefix }}"")] + static partial void M9(ILogger logger); + + [LoggerMessage(EventId = 10, Level = LogLevel.Debug, Message = ""}}suffix"")] + static partial void M10(ILogger logger); } ");