in src/Tasks/Microsoft.NET.Build.Tasks/JoinItems.cs [40:131]
protected override void ExecuteCore()
{
bool useLeftItemSpec = false;
bool useRightItemSpec = false;
if (string.Equals(ItemSpecToUse, "Left", StringComparison.OrdinalIgnoreCase))
{
useLeftItemSpec = true;
}
else if (string.Equals(ItemSpecToUse, "Right", StringComparison.OrdinalIgnoreCase))
{
useRightItemSpec = true;
}
else if (!string.IsNullOrEmpty(ItemSpecToUse))
{
throw new BuildErrorException(Strings.InvalidItemSpecToUse, ItemSpecToUse);
}
bool useAllLeftMetadata = LeftMetadata != null && LeftMetadata.Length == 1 && LeftMetadata[0] == "*";
bool useAllRightMetadata = RightMetadata != null && RightMetadata.Length == 1 && RightMetadata[0] == "*";
JoinResult = Left.Join(Right,
item => GetKeyValue(LeftKey, item),
item => GetKeyValue(RightKey, item),
(left, right) =>
{
// If including all metadata from left items and none from right items, just return left items directly
if (useAllLeftMetadata &&
(string.IsNullOrEmpty(LeftKey) || useLeftItemSpec) &&
(RightMetadata == null || RightMetadata.Length == 0))
{
return left;
}
// If including all metadata from right items and none from left items, just return the right items directly
if (useAllRightMetadata &&
(string.IsNullOrEmpty(RightKey) || useRightItemSpec) &&
(LeftMetadata == null || LeftMetadata.Length == 0))
{
return right;
}
string resultItemSpec;
if (useLeftItemSpec)
{
resultItemSpec = left.ItemSpec;
}
else if (useRightItemSpec)
{
resultItemSpec = right.ItemSpec;
}
else
{
resultItemSpec = GetKeyValue(LeftKey, left);
}
var ret = new TaskItem(resultItemSpec);
// Weird ordering here is to prefer left metadata in all cases, as CopyToMetadata doesn't overwrite any existing metadata
if (useAllLeftMetadata)
{
// CopyMetadata adds an OriginalItemSpec, which we don't want. So we subsequently remove it
left.CopyMetadataTo(ret);
ret.RemoveMetadata(MetadataKeys.OriginalItemSpec);
}
if (!useAllRightMetadata && RightMetadata != null)
{
foreach (string name in RightMetadata)
{
ret.SetMetadata(name, right.GetMetadata(name));
}
}
if (!useAllLeftMetadata && LeftMetadata != null)
{
foreach (string name in LeftMetadata)
{
ret.SetMetadata(name, left.GetMetadata(name));
}
}
if (useAllRightMetadata)
{
// CopyMetadata adds an OriginalItemSpec, which we don't want. So we subsequently remove it
right.CopyMetadataTo(ret);
ret.RemoveMetadata(MetadataKeys.OriginalItemSpec);
}
return (ITaskItem)ret;
},
StringComparer.OrdinalIgnoreCase).ToArray();
}