diff --git a/src/ResourcesGenerator/ResourceCreator.cs b/src/ResourcesGenerator/ResourceCreator.cs
index 1141e016..878b3dee 100644
--- a/src/ResourcesGenerator/ResourceCreator.cs
+++ b/src/ResourcesGenerator/ResourceCreator.cs
@@ -1,4 +1,5 @@
using System.Collections;
+
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@@ -51,6 +52,8 @@ public class ResourceCreator
"TaskFoundFromFactory",
"TaskFound",
"PropertyReassignment",
+ "PropertyAssignment",
+ "UninitializedPropertyRead",
"ProjectImported",
"ProjectImportSkippedMissingFile",
"ProjectImportSkippedInvalidFile",
@@ -66,16 +69,7 @@ public class ResourceCreator
"SearchPathsForMSBuildExtensionsPath",
"OverridingTarget",
"TryingExtensionsPath",
- "ProjectImported",
"DuplicateImport",
- "ProjectImportSkippedEmptyFile",
- "ProjectImportSkippedFalseCondition",
- "ProjectImportSkippedNoMatches",
- "ProjectImportSkippedMissingFile",
- "ProjectImportSkippedInvalidFile",
- "PropertyReassignment",
- "EvaluationStarted",
- "EvaluationFinished",
"CouldNotResolveSdk",
"ProjectImportSkippedExpressionEvaluatedToEmpty",
"SkipTargetBecauseOutputsUpToDate",
diff --git a/src/StructuredLogger/BinaryLogger/BinaryLogger.cs b/src/StructuredLogger/BinaryLogger/BinaryLogger.cs
index aecfac2b..09e7be2a 100644
--- a/src/StructuredLogger/BinaryLogger/BinaryLogger.cs
+++ b/src/StructuredLogger/BinaryLogger/BinaryLogger.cs
@@ -78,6 +78,8 @@ public sealed class BinaryLogger : ILogger
// BuildCheckTracingEvent, BuildCheckAcquisitionEvent, BuildSubmissionStartedEvent
// version 24:
// - new record kind: BuildCanceledEvent
+ // version 25:
+ // - add extra information to PropertyInitialValueSetEventArgs and PropertyReassignmentEventArgs and change parsing logic of Message property in them.
// This should be never changed.
// The minimum version of the binary log reader that can read log of above version.
@@ -85,7 +87,7 @@ public sealed class BinaryLogger : ILogger
// The current version of the binary log representation.
// Changes with each update of the binary log format.
- internal const int FileFormatVersion = 24;
+ internal const int FileFormatVersion = 25;
// The minimum version of the binary log reader that can read log of above version.
// This should be changed only when the binary log format is changed in a way that would prevent it from being
// read by older readers. (changing of the individual BuildEventArgs or adding new is fine - as reader can
diff --git a/src/StructuredLogger/BinaryLogger/BuildEventArgsReader.cs b/src/StructuredLogger/BinaryLogger/BuildEventArgsReader.cs
index 3e633070..710efd46 100644
--- a/src/StructuredLogger/BinaryLogger/BuildEventArgsReader.cs
+++ b/src/StructuredLogger/BinaryLogger/BuildEventArgsReader.cs
@@ -1360,7 +1360,25 @@ private BuildEventArgs ReadPropertyReassignmentEventArgs()
string message = fields.Message;
if (_fileFormatVersion >= 13)
{
- message = GetPropertyReassignmentMessage(propertyName, newValue, previousValue, location);
+ if (_fileFormatVersion >= 25)
+ {
+ var extendedEvent = new ExtendedPropertyReassignmentEventArgs(
+ propertyName,
+ previousValue,
+ newValue,
+ fields.File,
+ fields.LineNumber,
+ fields.ColumnNumber,
+ GetPropertyReassignmentMessage(propertyName, newValue, previousValue, $"{fields.File} ({fields.LineNumber},{fields.ColumnNumber})"));
+
+ SetCommonFields(extendedEvent, fields);
+
+ return extendedEvent;
+ }
+ else
+ {
+ message = GetPropertyReassignmentMessage(propertyName, newValue, previousValue, location);
+ }
}
var e = new PropertyReassignmentEventArgs(
@@ -1373,7 +1391,6 @@ private BuildEventArgs ReadPropertyReassignmentEventArgs()
fields.SenderName,
fields.Importance);
SetCommonFields(e, fields);
-
return e;
}
@@ -1381,10 +1398,16 @@ private BuildEventArgs ReadUninitializedPropertyReadEventArgs()
{
var fields = ReadBuildEventArgsFields(readImportance: true);
string propertyName = ReadDeduplicatedString();
+ string? message = fields.Message ?? string.Empty;
+
+ if (_fileFormatVersion >= 25)
+ {
+ message = FormatResourceStringIgnoreCodeAndKeyword(Strings.UninitializedPropertyRead, propertyName);
+ }
var e = new UninitializedPropertyReadEventArgs(
propertyName,
- fields.Message,
+ message,
fields.HelpKeyword,
fields.SenderName,
fields.Importance);
@@ -1401,11 +1424,24 @@ private BuildEventArgs ReadPropertyInitialValueSetEventArgs()
string propertyValue = ReadDeduplicatedString();
string propertySource = ReadDeduplicatedString();
- var e = new PropertyInitialValueSetEventArgs(
+ string message = fields.Message;
+ if (_fileFormatVersion >= 25)
+ {
+ string formattedSource = string.IsNullOrEmpty(fields.File)
+ ? propertySource
+ : $"{fields.File} ({fields.LineNumber},{fields.ColumnNumber})";
+
+ message = FormatResourceStringIgnoreCodeAndKeyword(Strings.PropertyAssignment, propertyName, propertyValue, formattedSource);
+ }
+
+ var e = new ExtendedPropertyInitialValueSetEventArgs(
propertyName,
propertyValue,
propertySource,
- fields.Message,
+ fields.File,
+ fields.LineNumber,
+ fields.ColumnNumber,
+ message,
fields.HelpKeyword,
fields.SenderName,
fields.Importance);
diff --git a/src/StructuredLogger/BinaryLogger/ExtendedPropertyInitialValueSetEventArgs.cs b/src/StructuredLogger/BinaryLogger/ExtendedPropertyInitialValueSetEventArgs.cs
new file mode 100644
index 00000000..fe649e2c
--- /dev/null
+++ b/src/StructuredLogger/BinaryLogger/ExtendedPropertyInitialValueSetEventArgs.cs
@@ -0,0 +1,53 @@
+using Microsoft.Build.Framework;
+
+namespace StructuredLogger.BinaryLogger
+{
+ internal class ExtendedPropertyInitialValueSetEventArgs : BuildMessageEventArgs
+ {
+ ///
+ /// Creates an instance of the class.
+ ///
+ /// The name of the property.
+ /// The value of the property.
+ /// The source of the property.
+ /// The file associated with the event.
+ /// The line number (0 if not applicable).
+ /// The column number (0 if not applicable).
+ /// The message of the property.
+ /// The help keyword.
+ /// The sender name of the event.
+ /// The importance of the message.
+ public ExtendedPropertyInitialValueSetEventArgs(
+ string propertyName,
+ string propertyValue,
+ string propertySource,
+ string file,
+ int line,
+ int column,
+ string message,
+ string helpKeyword = null,
+ string senderName = null,
+ MessageImportance importance = MessageImportance.Low)
+ : base(subcategory: null, code: null, file: file, lineNumber: line, columnNumber: column, 0, 0, message, helpKeyword, senderName, importance)
+ {
+ PropertyName = propertyName;
+ PropertyValue = propertyValue;
+ PropertySource = propertySource;
+ }
+
+ ///
+ /// The name of the property.
+ ///
+ public string PropertyName { get; set; }
+
+ ///
+ /// The value of the property.
+ ///
+ public string PropertyValue { get; set; }
+
+ ///
+ /// The source of the property.
+ ///
+ public string PropertySource { get; set; }
+ }
+}
diff --git a/src/StructuredLogger/BinaryLogger/ExtendedPropertyReassignmentEventArgs.cs b/src/StructuredLogger/BinaryLogger/ExtendedPropertyReassignmentEventArgs.cs
new file mode 100644
index 00000000..51e434fb
--- /dev/null
+++ b/src/StructuredLogger/BinaryLogger/ExtendedPropertyReassignmentEventArgs.cs
@@ -0,0 +1,53 @@
+using Microsoft.Build.Framework;
+
+namespace StructuredLogger.BinaryLogger
+{
+ internal class ExtendedPropertyReassignmentEventArgs : BuildMessageEventArgs
+ {
+ ///
+ /// Creates an instance of the class.
+ ///
+ /// The name of the property whose value was reassigned.
+ /// The previous value of the reassigned property.
+ /// The new value of the reassigned property.
+ /// The file associated with the event.
+ /// The line number (0 if not applicable).
+ /// The column number (0 if not applicable).
+ /// The message of the property.
+ /// The help keyword.
+ /// The sender name of the event.
+ /// The importance of the message.
+ public ExtendedPropertyReassignmentEventArgs(
+ string propertyName,
+ string previousValue,
+ string newValue,
+ string file,
+ int line,
+ int column,
+ string message,
+ string helpKeyword = null,
+ string senderName = null,
+ MessageImportance importance = MessageImportance.Low)
+ : base(subcategory: null, code: null, file: file, lineNumber: line, columnNumber: column, 0, 0, message, helpKeyword, senderName, importance)
+ {
+ PropertyName = propertyName;
+ PreviousValue = previousValue;
+ NewValue = newValue;
+ }
+
+ ///
+ /// The name of the property whose value was reassigned.
+ ///
+ public string PropertyName { get; set; }
+
+ ///
+ /// The previous value of the reassigned property.
+ ///
+ public string PreviousValue { get; set; }
+
+ ///
+ /// The new value of the reassigned property.
+ ///
+ public string NewValue { get; set; }
+ }
+}
diff --git a/src/StructuredLogger/Strings/Strings.cs b/src/StructuredLogger/Strings/Strings.cs
index 9faed348..00f54ffd 100644
--- a/src/StructuredLogger/Strings/Strings.cs
+++ b/src/StructuredLogger/Strings/Strings.cs
@@ -144,6 +144,10 @@ private static void InitializeRegex()
string propertyReassignment = GetPropertyReassignmentText();
PropertyReassignmentRegex = new Regex(propertyReassignment, RegexOptions.Compiled | RegexOptions.Singleline);
+ PropertyAssignment = GetString("PropertyAssignment");
+
+ UninitializedPropertyRead = GetString("UninitializedPropertyRead");
+
// MSBuild 17.6 shipped with this hardcoded to English (the first part of the regex), but it was switched to a different
// localized message in https://github.com/dotnet/msbuild/pull/8665. Support both here.
string deferredResponseFile = ("^(?:Included response file: {0}|" + GetString("PickedUpSwitchesFromAutoResponse") + ")$")
@@ -443,7 +447,9 @@ public static Regex CreateRegex(string text, int replacePlaceholders = 0, RegexO
public static string ProjectImportSkippedFalseCondition { get; set; }
public static string CouldNotResolveSdk { get; set; }
public static string ProjectImportSkippedExpressionEvaluatedToEmpty { get; set; }
+ public static string PropertyAssignment { get; set; }
public static string PropertyReassignment { get; set; }
+ public static string UninitializedPropertyRead { get; set; }
public static string ProjectImportSkippedNoMatches { get; set; }
public static string ProjectImportSkippedMissingFile { get; set; }
public static string ProjectImportSkippedInvalidFile { get; set; }
diff --git a/src/StructuredLogger/Strings/Strings.json b/src/StructuredLogger/Strings/Strings.json
index 508e8191..97c889b8 100644
--- a/src/StructuredLogger/Strings/Strings.json
+++ b/src/StructuredLogger/Strings/Strings.json
@@ -35,6 +35,8 @@
"TargetAlreadyCompleteSuccess": "Target \"{0}\" skipped. Previously built successfully.",
"TryingExtensionsPath": "Trying to import {0} using extensions path {1}",
"PropertyReassignment": "Property reassignment: $({0})=\"{1}\" (previous value: \"{2}\") at {3}",
+ "PropertyAssignment": "Property initial value: $({0})=\"{1}\". Source: {2}",
+ "UninitializedPropertyRead": "Read uninitialized property \"{0}\"",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "Project \"{0}\" was not imported by \"{1}\" at ({2},{3}), due to the expression evaluating to an empty string.",
"General.GlobalProperties": "Global Properties:",
"General.UndefineProperties": "Removing Properties:",
@@ -89,6 +91,8 @@
"TargetAlreadyCompleteSuccess": "Das Ziel \"{0}\" wurde übersprungen. Die vorherige Erstellung war erfolgreich.",
"TryingExtensionsPath": "Versucht {0} mithilfe des Erweiterungspfad {1} zu importieren.",
"PropertyReassignment": "Neuzuweisung der Eigenschaft: $({0})=\"{1}\" (vorheriger Wert: \"{2}\") unter {3}",
+ "PropertyAssignment": "Anfangswert der Eigenschaft: $({0})=\"{1}\". Quelle: {2}",
+ "UninitializedPropertyRead": "Nicht initialisierte Eigenschaft \"{0}\" gelesen",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "Das Projekt \"{0}\" wurde nicht von \"{1}\" bei ({2},{3}) importiert, weil der Ausdruck in eine leere Zeichenfolge ausgewertet wurde.",
"General.GlobalProperties": "Globale Eigenschaften:",
"General.UndefineProperties": "Eigenschaften werden entfernt:",
@@ -143,6 +147,8 @@
"TargetAlreadyCompleteSuccess": "La destinazione \"{0}\" è stata ignorata. La compilazione era stata completata in precedenza.",
"TryingExtensionsPath": "Si sta provando a importare {0} usando il percorso delle estensioni {1}",
"PropertyReassignment": "Riassegnazione della proprietà: $({0})=\"{1}\" (valore precedente: \"{2}\") in {3}",
+ "PropertyAssignment": "Valore iniziale della proprietà: $({0})=\"{1}\". Origine: {2}",
+ "UninitializedPropertyRead": "Lettura della proprietà non inizializzata \"{0}\"",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "Il progetto \"{0}\" non è stato importato da \"{1}\" alla posizione ({2},{3}) perché l'espressione restituisce una stringa vuota.",
"General.GlobalProperties": "Proprietà globali:",
"General.UndefineProperties": "Rimozione proprietà:",
@@ -197,6 +203,8 @@
"TargetAlreadyCompleteSuccess": "Se omitió el destino \"{0}\". Compilado previamente de forma correcta.",
"TryingExtensionsPath": "Intentando importar {0} con la ruta de acceso de extensiones {1}",
"PropertyReassignment": "Reasignación de propiedad: $({0})=\"{1}\" (valor anterior: \"{2}\") en {3}",
+ "PropertyAssignment": "Valor inicial de la propiedad: $({0})=\"{1}\". Origen: {2}",
+ "UninitializedPropertyRead": "Se leyó la propiedad no inicializada \"{0}\"",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "\"{1}\" no importó el proyecto \"{0}\" en ({2},{3}) porque la expresión se evalúa en una cadena vacía.",
"General.GlobalProperties": "Propiedades globales:",
"General.UndefineProperties": "Quitando propiedades:",
@@ -251,6 +259,8 @@
"TargetAlreadyCompleteSuccess": "Cible \"{0}\" ignorée. Elle a été générée.",
"TryingExtensionsPath": "Tentative d'importation de {0} en utilisant le chemin d'extensions {1}",
"PropertyReassignment": "Réassignation de propriété : $({0})=\"{1}\" (valeur précédente : \"{2}\") à {3}",
+ "PropertyAssignment": "Valeur initiale de la propriété: $({0})=\"{1}\". Source: {2}",
+ "UninitializedPropertyRead": "Lecture de la propriété non initialisée \"{0}\"",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "Le projet \"{0}\" n'a pas été importé par \"{1}\" sur ({2},{3}), car l'expression a la valeur d'une chaîne vide.",
"General.GlobalProperties": "Propriétés globales :",
"General.UndefineProperties": "Suppression des propriétés :",
@@ -305,6 +315,8 @@
"TargetAlreadyCompleteSuccess": "Cíl {0} byl vynechán. Předchozí sestavení bylo úspěšné.",
"TryingExtensionsPath": "Zkouší se import {0} pomocí cesty rozšíření {1}.",
"PropertyReassignment": "Opětovné přiřazení vlastnosti: $({0})={1} (předchozí hodnota: {2}) v {3}",
+ "PropertyAssignment": "Počáteční hodnota vlastnosti: $({0})=\"{1}\". Zdroj: {2}",
+ "UninitializedPropertyRead": "Čtení neinicializované vlastnosti \"{0}\"",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "{1} neimportoval projekt {0} v ({2},{3}), protože se výraz vyhodnocuje na prázdný řetězec.",
"General.GlobalProperties": "Globální vlastnosti:",
"General.UndefineProperties": "Odstraňování vlastností:",
@@ -359,6 +371,8 @@
"TargetAlreadyCompleteSuccess": "ターゲット \"{0}\" を省略しました。以前に正しくビルドされていました。",
"TryingExtensionsPath": "拡張パス {1} を使用して {0} をインポートしようとしています",
"PropertyReassignment": "プロパティの再代入: $({0})=\"{1}\" (以前の値: \"{2}\") {3}",
+ "PropertyAssignment": "プロパティの初期値: $({0})=\"{1}\". ソース: {2}",
+ "UninitializedPropertyRead": "初期化されていないプロパティ \"{0}\" を読み取りました",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "式の評価結果が空の文字列になったため、プロジェクト \"{0}\" は \"{1}\" によって ({2},{3}) でインポートされませんでした。",
"General.GlobalProperties": "グローバル プロパティ:",
"General.UndefineProperties": "プロパティの削除:",
@@ -413,6 +427,8 @@
"TargetAlreadyCompleteSuccess": "\"{0}\" 대상을 건너뜁니다. 이전에 빌드되었습니다.",
"TryingExtensionsPath": "확장 경로 {1}을(를) 사용하여 {0}을(를) 가져옵니다.",
"PropertyReassignment": "속성 재할당: $({0})={3}의 \"{1}\"(이전 값: \"{2}\")",
+ "PropertyAssignment": "속성 초기값: $({0})=\"{1}\" 소스: {2}",
+ "UninitializedPropertyRead": "초기화되지 않은 속성 \"{0}\" 읽음",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "빈 문자열로 평가되는 식 때문에 ({2},{3})의 \"{1}\"이(가) 프로젝트 \"{0}\"을(를) 가져오지 않았습니다.",
"General.GlobalProperties": "전역 속성:",
"General.UndefineProperties": "속성 제거:",
@@ -467,6 +483,8 @@
"TargetAlreadyCompleteSuccess": "Целевой объект \"{0}\" пропущен. Предыдущая сборка успешна.",
"TryingExtensionsPath": "Попытка импортировать \"{0}\" с помощью пути расширений {1}",
"PropertyReassignment": "Повторное назначение свойства: $({0})=\"{1}\" (предыдущее значение: \"{2}\") для {3}",
+ "PropertyAssignment": "Начальное значение свойства: $({0})=\"{1}\". Источник: {2}",
+ "UninitializedPropertyRead": "Чтение неинициализированного свойства \"{0}\"",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "Проект \"{0}\" не был импортирован \"{1}\" в ({2},{3}), так как результатом вычисления выражения была пустая строка.",
"General.GlobalProperties": "Глобальные свойства:",
"General.UndefineProperties": "Удаление свойств:",
@@ -521,6 +539,8 @@
"TargetAlreadyCompleteSuccess": "Pominięto element docelowy „{0}”. Wcześniejsza kompilacja powiodła się.",
"TryingExtensionsPath": "Próba zaimportowania elementu {0} przy użyciu ścieżki rozszerzeń {1}",
"PropertyReassignment": "Ponowne przypisanie właściwości: $({0})=„{1}” (poprzednia wartość: „{2}”) w {3}",
+ "PropertyAssignment": "Wartość początkowa właściwości: $({0})=\"{1}\". Źródło: {2}",
+ "UninitializedPropertyRead": "Odczytano niezainicjowaną właściwość \"{0}\"",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "Projekt „{0}” nie został zaimportowany przez projekt „{1}” o ({2},{3}) z powodu wyrażenia ocenianego jako pusty ciąg.",
"General.GlobalProperties": "Właściwości globalne:",
"General.UndefineProperties": "Usuwanie właściwości:",
@@ -575,6 +595,8 @@
"TargetAlreadyCompleteSuccess": "Destino \"{0}\" ignorado. Compilado anteriormente com êxito.",
"TryingExtensionsPath": "Tentando importar {0} usando o caminho das extensões {1}",
"PropertyReassignment": "Reatribuição de propriedade: $({0})=\"{1}\" (valor anterior: \"{2}\") em {3}",
+ "PropertyAssignment": "Valor inicial da propriedade: $({0})=\"{1}\". Origem: {2}",
+ "UninitializedPropertyRead":"Leitura de propriedade não inicializada \"{0}\"",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "O projeto \"{0}\" não foi importado por \"{1}\" em ({2},{3}), porque a expressão foi avaliada como uma cadeia de caracteres vazia.",
"General.GlobalProperties": "Propriedades globais:",
"General.UndefineProperties": "Removendo Propriedades:",
@@ -629,6 +651,8 @@
"TargetAlreadyCompleteSuccess": "\"{0}\" hedefi atlandı. Önceden başarılı bir şekilde derlenmişti.",
"TryingExtensionsPath": "{1} uzantı yolları kullanılarak {0} içeri aktarılmaya çalışılıyor",
"PropertyReassignment": "Özellik yeniden ataması: $({0})=\"{1}\" (önceki değer: \"{2}\") konum: {3}",
+ "PropertyAssignment": "Özellik başlangıç değeri: $({0})=\"{1}\". Kaynak: {2}",
+ "UninitializedPropertyRead": "Başlatılmamış özellik \"{0}\" okundu",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "\"{0}\" adlı proje, ifadenin boş dize olarak değerlendirilmesi nedeniyle ({2},{3}) konumundaki \"{1}\" tarafından içeri aktarılmadı.",
"General.GlobalProperties": "Genel Özellikler:",
"General.UndefineProperties": "Özellikler kaldırılıyor:",
@@ -683,6 +707,8 @@
"TargetAlreadyCompleteSuccess": "已跳过目标“{0}”。以前的生成已成功。",
"TryingExtensionsPath": "尝试使用扩展路径 {1} 导入 {0}",
"PropertyReassignment": "在 {3} 处重新分配属性: $({0})=“{1}”(先前值:“{2}”)",
+ "PropertyAssignment": "属性初始值: $({0})=\"{1}\"来源: {2}",
+ "UninitializedPropertyRead": "读取未初始化的属性 \"{0}\"",
"ProjectImportSkippedExpressionEvaluatedToEmpty": "由于表达式评估为空字符串,因此项目“{0}”不由 ({2}、{3}) 处的“{1}”导入。",
"General.GlobalProperties": "全局属性:",
"General.UndefineProperties": "移除属性:",