forked from dotnet/sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
JoinItems.cs
145 lines (122 loc) · 5.24 KB
/
JoinItems.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.Linq;
namespace Microsoft.NET.Build.Tasks
{
public class JoinItems : TaskBase
{
[Required]
public ITaskItem[] Left { get; set; }
[Required]
public ITaskItem[] Right { get; set; }
// LeftKey and RightKey: The metadata to join on. If not set, then use the ItemSpec
public string LeftKey { get; set; }
public string RightKey { get; set; }
// Set to "Left" or "Right" to use that itemspec in results. Leave blank to set itemspec based on the joined key value
public string ItemSpecToUse { get; set; }
// LeftMetadata and RightMetadata: The metadata names to include in the result. Specify "*" to include all metadata
public string[] LeftMetadata { get; set; }
public string[] RightMetadata { get; set; }
[Output]
public ITaskItem[] JoinResult
{
get; private set;
}
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();
}
static string GetKeyValue(string key, ITaskItem item)
{
if (string.IsNullOrEmpty(key))
{
return item.ItemSpec;
}
else
{
return item.GetMetadata(key);
}
}
}
}