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
32 changes: 32 additions & 0 deletions src/MSBuild.UnitTests/XMake_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,38 @@ public void GetStarOutputsToFileIfRequested(string extraSwitch, string result)
result.ShouldContain("MSB1068");
}

/// <summary>
/// Regression test for issue where getTargetResult/getItem would throw an unhandled exception
/// when the item spec contained illegal path characters (e.g. compiler command line flags).
/// </summary>
[Theory]
[InlineData("-getTargetResult:GetCompileCommands", "\"Result\": \"Success\"")]
[InlineData("-getItem:CompileCommands", "\"Identity\":")]
public void GetTargetResultWithIllegalPathCharacters(string extraSwitch, string expectedContent)
{
using TestEnvironment env = TestEnvironment.Create();
// Create a project that mimics the ClangTidy target - it outputs items with illegal path characters
// (compiler command line flags) as the item spec.
TransientTestFile project = env.CreateFile("testProject.csproj", @"
<Project>
<ItemGroup>
<CompileCommands Include=""/c /nologo /W3 /WX- /diagnostics:column /Od /D _DEBUG"" />
</ItemGroup>

<Target Name=""GetCompileCommands"" Returns=""@(CompileCommands)"">
<ItemGroup>
<CompileCommands Include=""/c /fp:precise /permissive- /Fa&quot;Debug\\&quot; /Fo&quot;Debug\\&quot; /Gd --target=amd64-pc-windows-msvc /TP"" />
</ItemGroup>
</Target>
</Project>
");
string results = RunnerUtilities.ExecMSBuild($" {project.Path} /t:GetCompileCommands {extraSwitch}", out bool success);
// The build should succeed instead of throwing an unhandled exception
success.ShouldBeTrue(results);
// The output should contain the expected content
results.ShouldContain(expectedContent);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
Expand Down
63 changes: 60 additions & 3 deletions src/MSBuild/JsonOutputFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ internal void AddItemInstancesInJsonFormat(string[] itemNames, ProjectInstance p
continue;
}

jsonItem[metadatumName] = item.GetMetadataValue(metadatumName);
jsonItem[metadatumName] = TryGetMetadataValue(item, metadatumName);
}

itemArray.Add(jsonItem);
Expand Down Expand Up @@ -108,7 +108,7 @@ internal void AddItemsInJsonFormat(string[] itemNames, Project project)
continue;
}

jsonItem[metadatumName] = item.GetMetadataValue(metadatumName);
jsonItem[metadatumName] = TryGetMetadataValue(item, metadatumName);
}

itemArray.Add(jsonItem);
Expand Down Expand Up @@ -147,7 +147,7 @@ internal void AddTargetResultsInJsonFormat(string[] targetNames, BuildResult res
continue;
}

jsonItem[metadatumName] = item.GetMetadata(metadatumName);
jsonItem[metadatumName] = TryGetMetadata(item, metadatumName);
}

outputArray.Add(jsonItem);
Expand All @@ -159,5 +159,62 @@ internal void AddTargetResultsInJsonFormat(string[] targetNames, BuildResult res

_topLevelNode["TargetResults"] = targetResultsNode;
}

/// <summary>
/// Attempts to get metadata from an ITaskItem. If the metadata is a built-in metadata
/// (like FullPath, Directory, etc.) and the item spec contains illegal path characters,
/// this will catch the InvalidOperationException and return an empty string.
/// </summary>
private static string TryGetMetadata(ITaskItem item, string metadataName)
{
try
{
return item.GetMetadata(metadataName);
}
catch (InvalidOperationException)
{
// Built-in metadata like FullPath, Directory, etc. require path computation.
// If the item spec contains illegal path characters, return empty string.
return string.Empty;
}
}

/// <summary>
/// Attempts to get metadata value from a ProjectItemInstance. If the metadata is a built-in metadata
/// (like FullPath, Directory, etc.) and the item spec contains illegal path characters,
/// this will catch the InvalidOperationException and return an empty string.
/// </summary>
private static string TryGetMetadataValue(ProjectItemInstance item, string metadataName)
{
try
{
return item.GetMetadataValue(metadataName);
}
catch (InvalidOperationException)
{
// Built-in metadata like FullPath, Directory, etc. require path computation.
// If the item spec contains illegal path characters, return empty string.
return string.Empty;
}
}

/// <summary>
/// Attempts to get metadata value from a ProjectItem. If the metadata is a built-in metadata
/// (like FullPath, Directory, etc.) and the item spec contains illegal path characters,
/// this will catch the InvalidOperationException and return an empty string.
/// </summary>
private static string TryGetMetadataValue(ProjectItem item, string metadataName)
{
try
{
return item.GetMetadataValue(metadataName);
}
catch (InvalidOperationException)
{
// Built-in metadata like FullPath, Directory, etc. require path computation.
// If the item spec contains illegal path characters, return empty string.
return string.Empty;
}
}
}
}