Skip to content

Commit c4d43ba

Browse files
authored
Merge pull request github#3797 from hvitved/csharp/dataflow/more-collection-tests
C#: More data-flow collection tests
2 parents cf0cd00 + 3f91aa3 commit c4d43ba

File tree

2 files changed

+456
-231
lines changed

2 files changed

+456
-231
lines changed

csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.cs

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ public class CollectionFlow
77
{
88
public class A { }
99

10+
public A[] As;
11+
1012
public void ArrayInitializerFlow()
1113
{
1214
var a = new A();
@@ -25,6 +27,24 @@ public void ArrayInitializerNoFlow(A other)
2527
Sink(First(@as)); // no flow
2628
}
2729

30+
public void ArrayInitializerCSharp6Flow()
31+
{
32+
var a = new A();
33+
var c = new CollectionFlow() { As = { [0] = a } };
34+
Sink(c.As[0]); // flow [MISSING]
35+
SinkElem(c.As); // flow [MISSING]
36+
Sink(First(c.As)); // flow [MISSING]
37+
}
38+
39+
public void ArrayInitializerCSharp6NoFlow(A other)
40+
{
41+
var a = new A();
42+
var c = new CollectionFlow() { As = { [0] = other } };
43+
Sink(c.As[0]); // no flow
44+
SinkElem(c.As); // no flow
45+
Sink(First(c.As)); // no flow
46+
}
47+
2848
public void ArrayAssignmentFlow()
2949
{
3050
var a = new A();
@@ -144,6 +164,28 @@ public void DictionaryValueInitializerNoFlow(A other)
144164
Sink(DictValuesFirst(dict)); // no flow
145165
}
146166

167+
public void DictionaryValueInitializerCSharp6Flow()
168+
{
169+
var a = new A();
170+
var dict = new Dictionary<int, A>() { [0] = a };
171+
Sink(dict[0]); // flow [MISSING]
172+
SinkDictValue(dict); // flow [MISSING]
173+
Sink(DictIndexZero(dict)); // flow [MISSING]
174+
Sink(DictFirstValue(dict)); // flow [MISSING]
175+
Sink(DictValuesFirst(dict)); // flow [MISSING]
176+
}
177+
178+
public void DictionaryValueInitializerCSharp6NoFlow(A other)
179+
{
180+
var a = new A();
181+
var dict = new Dictionary<int, A>() { [0] = other };
182+
Sink(dict[0]); // no flow
183+
SinkDictValue(dict); // no flow
184+
Sink(DictIndexZero(dict)); // no flow
185+
Sink(DictFirstValue(dict)); // no flow
186+
Sink(DictValuesFirst(dict)); // no flow
187+
}
188+
147189
public void DictionaryKeyInitializerFlow()
148190
{
149191
var a = new A();
@@ -163,6 +205,25 @@ public void DictionaryKeyInitializerNoFlow(A other)
163205
Sink(DictFirstKey(dict)); // no flow
164206
}
165207

208+
public void DictionaryKeyInitializerCSharp6Flow()
209+
{
210+
var a = new A();
211+
var dict = new Dictionary<A, int>() { [a] = 0 };
212+
Sink(dict.Keys.First()); // flow [MISSING]
213+
SinkDictKey(dict); // flow [MISSING]
214+
Sink(DictKeysFirst(dict)); // flow [MISSING]
215+
Sink(DictFirstKey(dict)); // flow [MISSING]
216+
}
217+
218+
public void DictionaryKeyInitializerCSharp6NoFlow(A other)
219+
{
220+
var dict = new Dictionary<A, int>() { [other] = 0 };
221+
Sink(dict.Keys.First()); // no flow
222+
SinkDictKey(dict); // no flow
223+
Sink(DictKeysFirst(dict)); // no flow
224+
Sink(DictFirstKey(dict)); // no flow
225+
}
226+
166227
public void ForeachFlow()
167228
{
168229
var a = new A();
@@ -205,6 +266,98 @@ public void ListGetEnumeratorFlow()
205266
Sink(enumerator.Current); // flow [MISSING]
206267
}
207268

269+
public void ListGetEnumeratorNoFlow(A other)
270+
{
271+
var list = new List<A>();
272+
list.Add(other);
273+
var enumerator = list.GetEnumerator();
274+
while (enumerator.MoveNext())
275+
Sink(enumerator.Current); // no flow
276+
}
277+
278+
public void SelectFlow()
279+
{
280+
var a = new A();
281+
var list = new List<KeyValuePair<A, int>>();
282+
list.Add(new KeyValuePair<A, int>(a, 0));
283+
list.Select(kvp =>
284+
{
285+
Sink(kvp.Key); // flow
286+
return kvp.Value;
287+
});
288+
}
289+
290+
public void SelectNoFlow()
291+
{
292+
var a = new A();
293+
var list = new List<KeyValuePair<A, int>>();
294+
list.Add(new KeyValuePair<A, int>(a, 0));
295+
list.Select(kvp =>
296+
{
297+
Sink(kvp.Value); // no flow
298+
return kvp.Value;
299+
});
300+
}
301+
302+
void SetArray(A[] array, A element) => array[0] = element;
303+
304+
public void ArraySetterFlow()
305+
{
306+
var a = new A();
307+
var @as = new A[1];
308+
SetArray(@as, a);
309+
Sink(@as[0]); // flow [MISSING]
310+
SinkElem(@as); // flow [MISSING]
311+
Sink(First(@as)); // flow [MISSING]
312+
}
313+
314+
public void ArraySetterNoFlow(A other)
315+
{
316+
var a = new A();
317+
var @as = new A[1];
318+
SetArray(@as, other);
319+
Sink(@as[0]); // no flow
320+
SinkElem(@as); // no flow
321+
Sink(First(@as)); // no flow
322+
}
323+
324+
void SetList(List<A> list, A element) => list.Add(element);
325+
326+
public void ListSetterFlow()
327+
{
328+
var a = new A();
329+
var list = new List<A>();
330+
SetList(list, a);
331+
Sink(list[0]); // flow
332+
SinkListElem(list); // flow
333+
Sink(ListFirst(list)); // flow
334+
}
335+
336+
public void ListSetterNoFlow(A other)
337+
{
338+
var list = new List<A>();
339+
SetList(list, other);
340+
Sink(list[0]); // no flow
341+
SinkListElem(list); // no flow
342+
Sink(ListFirst(list)); // no flow
343+
}
344+
345+
public void ParamsFlow()
346+
{
347+
SinkParams(new A()); // flow [MISSING]
348+
SinkParams(null, new A()); // flow [MISSING]
349+
SinkParams(null, new A(), null); // flow [MISSING]
350+
SinkParams(new A[] { new A() }); // flow
351+
}
352+
353+
public void ParamsNoFlow(A other)
354+
{
355+
SinkParams(other); // no flow
356+
SinkParams(null, other); // no flow
357+
SinkParams(null, other, null); // no flow
358+
SinkParams(new A[] { other }); // no flow
359+
}
360+
208361
public static void Sink<T>(T t) { }
209362

210363
public static void SinkElem<T>(T[] ts) => Sink(ts[0]);
@@ -228,4 +381,6 @@ public static void Sink<T>(T t) { }
228381
public static T DictKeysFirst<T>(IDictionary<T, int> dict) => dict.Keys.First();
229382

230383
public static T DictFirstKey<T>(IDictionary<T, int> dict) => dict.First().Key;
384+
385+
public static void SinkParams<T>(params T[] args) => Sink(args[0]);
231386
}

0 commit comments

Comments
 (0)