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
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
12 changes: 12 additions & 0 deletions src/Build/Logging/BinaryLogger/BuildEventArgsWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,18 @@ private void WriteTaskItemList(IEnumerable items, bool writeMetadata = true)
{
Write(taskItem, writeMetadata);
}
else if (item is IItemData itemData)
{
WriteDeduplicatedString(itemData.EvaluatedInclude);
if (writeMetadata)
{
Write(itemData.EnumerateMetadata());
}
else
{
Write((byte)0);
}
}
else
{
WriteDeduplicatedString(item?.ToString() ?? ""); // itemspec
Expand Down
Loading