Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
8 changes: 8 additions & 0 deletions src/Build.UnitTests/BackEnd/TranslationHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,14 @@ internal static string GetTaskItemString(object item)
sb.Append($";{name}={value}");
}
}
else if (item is IItemData itemData)
{
sb.Append(itemData.EvaluatedInclude);
foreach (var kvp in itemData.EnumerateMetadata())
{
sb.Append($";{kvp.Key}={kvp.Value}");
}
}
else
{
sb.Append(Convert.ToString(item));
Expand Down
51 changes: 51 additions & 0 deletions src/Build.UnitTests/BuildEventArgsSerialization_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,57 @@ public void RoundtripProjectEvaluationFinishedEventArgs()
e => TranslationHelpers.GetMultiItemsString(e.Items));
}

/// <summary>
/// Tests that items implementing IItemData (like ProjectItem) are properly serialized in binary logs.
/// This regression test ensures that -getitem properly logs item values instead of type names.
/// </summary>
[Fact]
public void RoundtripProjectEvaluationFinishedEventArgsWithIItemData()
{
var itemDataWithMetadata = new TestItemData(
"TestItemSpec",
new Dictionary<string, string> { { "MetadataKey", "MetadataValue" }, { "Another", "Data" } });
var args = new ProjectEvaluationFinishedEventArgs(
ResourceUtilities.GetResourceString("EvaluationFinished"),
@"C:\foo\bar.proj")
{
BuildEventContext = BuildEventContext.Invalid,
ProjectFile = @"C:\foo\bar.proj",
GlobalProperties = new Dictionary<string, string>() { { "GlobalKey", "GlobalValue" } },
Properties = new List<DictionaryEntry>() { new DictionaryEntry("Key", "Value") },
Items = new List<DictionaryEntry>() { new DictionaryEntry("ItemType", itemDataWithMetadata) }
};

Roundtrip(args,
e => e.Message,
e => e.ProjectFile,
e => TranslationHelpers.GetPropertiesString(e.GlobalProperties),
e => TranslationHelpers.GetPropertiesString(e.Properties),
e => TranslationHelpers.GetMultiItemsString(e.Items));
}

/// <summary>
/// Test implementation of IItemData for testing serialization of non-ITaskItem items.
/// This simulates how ProjectItem (which implements IItemData but not ITaskItem) is serialized.
/// </summary>
private sealed class TestItemData : IItemData
{
private readonly string _evaluatedInclude;
private readonly Dictionary<string, string> _metadata;

public TestItemData(string evaluatedInclude, Dictionary<string, string> metadata = null)
{
_evaluatedInclude = evaluatedInclude;
_metadata = metadata ?? new Dictionary<string, string>();
}

/// <inheritdoc />
public string EvaluatedInclude => _evaluatedInclude;

/// <inheritdoc />
public IEnumerable<KeyValuePair<string, string>> EnumerateMetadata() => _metadata;
}

[Fact]
public void RoundtripProjectEvaluationFinishedEventArgsWithProfileData()
{
Expand Down
18 changes: 18 additions & 0 deletions src/Build/Logging/BinaryLogger/BuildEventArgsWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,24 @@ private void WriteTaskItemList(IEnumerable items, bool writeMetadata = true)
{
Write(taskItem, writeMetadata);
}
else if (item is IItemData itemData)
{
WriteDeduplicatedString(itemData.EvaluatedInclude);
if (writeMetadata)
{
foreach (var kvp in itemData.EnumerateMetadata())
{
nameValueListBuffer.Add(kvp);
}

WriteNameValueList();
nameValueListBuffer.Clear();
Comment thread
YuliiaKovalova marked this conversation as resolved.
Outdated
}
else
{
Write((byte)0);
}
}
else
{
WriteDeduplicatedString(item?.ToString() ?? ""); // itemspec
Expand Down
Loading