Skip to content

Commit 9d29dee

Browse files
committed
C#: Add static call graph tests
1 parent b6a7661 commit 9d29dee

File tree

5 files changed

+495
-0
lines changed

5 files changed

+495
-0
lines changed
Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
// Out of scope:
2+
// - overloading
3+
// - accessibility
4+
// - other callables than methods
5+
// - generics
6+
7+
namespace N1
8+
{
9+
public class C1
10+
{
11+
public void // $ TypeMention=System.Void
12+
M1()
13+
{ }
14+
15+
public void // $ TypeMention=System.Void
16+
M2(C1 c1) // $ TypeMention=N1.C1
17+
{
18+
M1(); // $ StaticTarget=N1.C1.M1
19+
this.M1(); // $ StaticTarget=N1.C1.M1
20+
21+
c1.M1(); // $ StaticTarget=N1.C1.M1
22+
23+
C1 c2 = null; // $ TypeMention=N1.C1
24+
c2.M1(); // $ StaticTarget=N1.C1.M1
25+
26+
var c3 = new C1(); // $ TypeMention=N1.C1 $ StaticTarget=N1.C1.C1
27+
c3.M1(); // $ StaticTarget=N1.C1.M1
28+
29+
M3(). // $ StaticTarget=N1.C1.M3
30+
M1(); // $ StaticTarget=N1.C1.M1
31+
32+
var c4 = M3(); // $ StaticTarget=N1.C1.M3
33+
c4.M1(); // $ StaticTarget=N1.C1.M1
34+
}
35+
36+
public C1 M3() => throw null; // $ TypeMention=N1.C1
37+
} // $ Class=N1.C1
38+
}
39+
40+
namespace N2
41+
{
42+
using N1;
43+
44+
public class C1
45+
{
46+
public void // $ TypeMention=System.Void
47+
M1(
48+
C1 c1 = null, // $ TypeMention=N2.C1
49+
N1.C1 c2 = null // $ TypeMention=N1.C1
50+
)
51+
{
52+
c1.M1(); // $ StaticTarget=N2.C1.M1
53+
c2.M1(); // $ StaticTarget=N1.C1.M1
54+
}
55+
} // $ Class=N2.C1
56+
57+
public class C2 : C1 // $ TypeMention=N2.C1
58+
{
59+
public void // $ TypeMention=System.Void
60+
M2()
61+
{
62+
M1(); // $ StaticTarget=N2.C1.M1
63+
this.M1(); // $ StaticTarget=N2.C1.M1
64+
base.M1(); // $ StaticTarget=N2.C1.M1
65+
66+
C1 c1 = // $ TypeMention=N2.C1
67+
new C2(); // $ TypeMention=N2.C2 $ StaticTarget=N2.C2.C2
68+
c1.M1(); // $ StaticTarget=N2.C1.M1
69+
}
70+
} // $ Class=N2.C2
71+
72+
public class C3 : C2 // $ TypeMention=N2.C2
73+
{
74+
public new void // $ TypeMention=System.Void
75+
M2()
76+
{
77+
M2(); // $ StaticTarget=N2.C3.M2
78+
C3 c3 = null; // $ TypeMention=N2.C3
79+
c3.M2(); // $ StaticTarget=N2.C3.M2
80+
C2 c2 = c3; // $ TypeMention=N2.C2
81+
c2.M2(); // $ StaticTarget=N2.C2.M2
82+
}
83+
} // $ Class=N2.C3
84+
}
85+
86+
namespace N3
87+
{
88+
using N1;
89+
90+
public class C2
91+
{
92+
C1 Field1; // $ TypeMention=N1.C1
93+
N1.C1 Field2; // $ TypeMention=N1.C1
94+
C2 Field3; // $ TypeMention=N3.C2
95+
96+
C1 Prop1 => null; // $ TypeMention=N1.C1
97+
N1.C1 Prop2 => null; // $ TypeMention=N1.C1
98+
C2 Prop3 { get; set; } // $ TypeMention=N3.C2
99+
100+
public void // $ TypeMention=System.Void
101+
M1(
102+
C1 c1, // $ TypeMention=N1.C1
103+
N1.C1 c2 // $ TypeMention=N1.C1
104+
)
105+
{
106+
c1.M1(); // $ StaticTarget=N1.C1.M1
107+
c2.M1(); // $ StaticTarget=N1.C1.M1
108+
109+
Field1.M1(); // $ StaticTarget=N1.C1.M1
110+
Field2.M1(); // $ StaticTarget=N1.C1.M1
111+
Field3.M1(null, null); // $ StaticTarget=N3.C2.M1
112+
{
113+
// shadows outer field
114+
C2 Field1 = null; // $ TypeMention=N3.C2
115+
Field1.M1(null, null); // $ StaticTarget=N3.C2.M1
116+
this.Field1.M1(); // $ StaticTarget=N1.C1.M1
117+
}
118+
119+
Prop1. // $ StaticTarget=N3.C2.get_Prop1
120+
M1(); // $ StaticTarget=N1.C1.M1
121+
Prop2. // $ StaticTarget=N3.C2.get_Prop2
122+
M1(); // $ StaticTarget=N1.C1.M1
123+
Prop3. // $ StaticTarget=N3.C2.get_Prop3
124+
M1(null, null); // $ StaticTarget=N3.C2.M1
125+
Prop3 = null; // $ StaticTarget=N3.C2.set_Prop3
126+
{
127+
// shadows outer property
128+
N2.C2 Prop1 = null; // $ TypeMention=N2.C2
129+
Prop1.M1(); // $ StaticTarget=N2.C1.M1
130+
this.Prop1. // $ StaticTarget=N3.C2.get_Prop1
131+
M1(); // $ StaticTarget=N1.C1.M1
132+
}
133+
}
134+
} // $ Class=N3.C2
135+
}
136+
137+
namespace N4
138+
{
139+
public class C1
140+
{
141+
public virtual void // $ TypeMention=System.Void
142+
M1()
143+
{
144+
this.M1(); // $ StaticTarget=N4.C1.M1
145+
}
146+
} // $ Class=N4.C1
147+
148+
public class C2 : C1 // $ TypeMention=N4.C1
149+
{
150+
public override void // $ TypeMention=System.Void
151+
M1()
152+
{
153+
this.M1(); // $ StaticTarget=N4.C2.M1
154+
base.M1(); // $ StaticTarget=N4.C1.M1
155+
}
156+
} // $ Class=N4.C2
157+
}
158+
159+
namespace N5
160+
{
161+
public class C1 : N4.C1 // $ TypeMention=N4.C1
162+
{
163+
public void // $ TypeMention=System.Void
164+
M2()
165+
{
166+
this.M1(); // $ StaticTarget=N4.C1.M1
167+
}
168+
} // $ Class=N5.C1
169+
170+
public class C2 : N4.C1 // $ TypeMention=N4.C1
171+
{
172+
public override void // $ TypeMention=System.Void
173+
M1()
174+
{
175+
this.M1(); // $ StaticTarget=N5.C2.M1
176+
base.M1(); // $ StaticTarget=N4.C1.M1
177+
}
178+
} // $ Class=N5.C2
179+
}
180+
181+
namespace N6
182+
{
183+
using N4;
184+
using NamespaceAlias = N5;
185+
using TypeAlias = N5.C2; // $ TypeMention=N5.C2
186+
using C2 = N5.C2; // $ TypeMention=N5.C2
187+
188+
public class C1
189+
{
190+
public void // $ TypeMention=System.Void
191+
M1(
192+
NamespaceAlias::C2 c1, // $ TypeMention=N5.C2
193+
NamespaceAlias.C2 c2, // $ TypeMention=N5.C2
194+
TypeAlias c3, // $ TypeMention=N5.C2
195+
C2 c4, // $ TypeMention=N5.C2
196+
global::N5.C1 c5 // $ TypeMention=N5.C1
197+
)
198+
{
199+
c1.M1(); // $ StaticTarget=N5.C2.M1
200+
c2.M1(); // $ StaticTarget=N5.C2.M1
201+
c3.M1(); // $ StaticTarget=N5.C2.M1
202+
c4.M1(); // $ StaticTarget=N5.C2.M1
203+
c5.M1(); // $ StaticTarget=N4.C1.M1
204+
}
205+
206+
public static void // $ TypeMention=System.Void
207+
M2()
208+
{ }
209+
210+
public static void // $ TypeMention=System.Void
211+
M3()
212+
{ }
213+
214+
public static C1 // $ TypeMention=N6.C1
215+
Prop1
216+
{ get; }
217+
218+
public static C1 // $ TypeMention=N6.C1
219+
Prop2
220+
{ get; }
221+
} // $ Class=N6.C1
222+
}
223+
224+
namespace N7
225+
{
226+
public class C1
227+
{
228+
public void // $ TypeMention=System.Void
229+
M1()
230+
{
231+
N6.C1. // $ TypeMention=N6.C1
232+
M2(); // $ StaticTarget=N6.C1.M2
233+
}
234+
} // $ Class=N7.C1
235+
}
236+
237+
namespace N8
238+
{
239+
using static N6.C1; // $ TypeMention=N6.C1
240+
241+
public class C1
242+
{
243+
public void // $ TypeMention=System.Void
244+
M1()
245+
{
246+
M2(); // $ StaticTarget=N6.C1.M2
247+
248+
var x = Prop1; // $ StaticTarget=N6.C1.get_Prop1
249+
250+
N6.C1. // $ TypeMention=N6.C1
251+
M2(); // $ StaticTarget=N6.C1.M2
252+
253+
x = N6.C1. // $ TypeMention=N6.C1
254+
Prop1; // $ StaticTarget=N6.C1.get_Prop1
255+
256+
M3(); // $ StaticTarget=N8.C1.M3
257+
258+
var y = Prop2; // $ StaticTarget=N8.C1.get_Prop2
259+
260+
C1. // $ TypeMention=N8.C1
261+
M3(); // $ StaticTarget=N8.C1.M3
262+
263+
y = C1. // $ TypeMention=N8.C1
264+
Prop2; // $ StaticTarget=N8.C1.get_Prop2
265+
266+
C1. // $ TypeMention=N8.C1
267+
M3(); // $ StaticTarget=N8.C1.M3
268+
269+
y = C1. // $ TypeMention=N8.C1
270+
Prop2; // $ StaticTarget=N8.C1.get_Prop2
271+
272+
N8.C1. // $ TypeMention=N8.C1
273+
M3(); // $ StaticTarget=N8.C1.M3
274+
275+
y = N8.C1. // $ TypeMention=N8.C1
276+
Prop2; // $ StaticTarget=N8.C1.get_Prop2
277+
}
278+
279+
public static void // $ TypeMention=System.Void
280+
M3()
281+
{ }
282+
283+
public static C1 // $ TypeMention=N8.C1
284+
Prop2
285+
{ get; }
286+
287+
class C2
288+
{
289+
void // $ TypeMention=System.Void
290+
M()
291+
{
292+
M2(); // $ StaticTarget=N6.C1.M2
293+
M3(); // $ StaticTarget=N8.C1.M3
294+
var x = Prop1; // $ StaticTarget=N6.C1.get_Prop1
295+
var y = Prop2; // $ StaticTarget=N8.C1.get_Prop2
296+
}
297+
298+
} // $ Class=N8.C1+C2
299+
} // $ Class=N8.C1
300+
}
301+
302+
namespace N9
303+
{
304+
public class C1
305+
{
306+
public C1(int i) { }
307+
308+
public static int M1() => 5;
309+
} // $ Class=N9.C1
310+
311+
public class C2 :
312+
C1 // $ TypeMention=N9.C1
313+
{
314+
C2() : base(
315+
M1() // $ StaticTarget=N9.C1.M1
316+
) // $ StaticTarget=N9.C1.C1
317+
{ }
318+
319+
C2(int i)
320+
: this() // $ StaticTarget=N9.C2.C2()
321+
{ }
322+
} // $ Class=N9.C2
323+
}
324+
325+
namespace N10
326+
{
327+
public class X1
328+
{
329+
public int M1() => 5;
330+
}// $ Class=N10.X1
331+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
| CallGraph.cs:77:13:77:16 | call to method M2 | Unexpected result: StaticTarget=N2.C3.M2() |
2+
| CallGraph.cs:77:19:77:44 | // ... | Missing result:StaticTarget=N2.C3.M2 |
3+
| CallGraph.cs:79:13:79:19 | call to method M2 | Unexpected result: StaticTarget=N2.C3.M2() |
4+
| CallGraph.cs:79:22:79:47 | // ... | Missing result:StaticTarget=N2.C3.M2 |
5+
| CallGraph.cs:314:16:314:19 | call to constructor C1 | Unexpected result: StaticTarget=N9.C1.C1 |
6+
| CallGraph.cs:316:21:316:46 | // ... | Missing result:StaticTarget=N9.C1.C1 |
7+
| CallGraph.cs:320:15:320:18 | call to constructor C2 | Unexpected result: StaticTarget=N9.C2.C2 |
8+
| CallGraph.cs:320:22:320:49 | // ... | Missing result:StaticTarget=N9.C2.C2() |
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import csharp
2+
import TestUtilities.InlineExpectationsTest
3+
4+
private predicate isOverloaded(Callable c) {
5+
exists(Callable other |
6+
c.getDeclaringType().hasCallable(other) and
7+
other.getName() = c.getName() and
8+
other != c
9+
)
10+
}
11+
12+
private string printParameterType(Parameter p) {
13+
if p.isParams()
14+
then result = "params:" + p.getType().(ArrayType).getElementType().getQualifiedName() + "[]"
15+
else result = p.getType().getQualifiedName()
16+
}
17+
18+
private string printSig(Callable c) {
19+
isOverloaded(c) and
20+
result =
21+
concat(Parameter p, int i | p = c.getParameter(i) | printParameterType(p), "," order by i)
22+
}
23+
24+
class CallGraphTest extends InlineExpectationsTest {
25+
CallGraphTest() { this = "CallGraphTest" }
26+
27+
override string getARelevantTag() { result = "StaticTarget" }
28+
29+
override predicate hasActualResult(Location location, string element, string tag, string value) {
30+
exists(Call c, string sig, Callable target |
31+
element = c.toString() and
32+
tag = "StaticTarget" and
33+
target = c.getTarget() and
34+
(if isOverloaded(target) then sig = "(" + printSig(target) + ")" else sig = "") and
35+
value = target.getQualifiedName() + sig and
36+
c.getLocation() = location and
37+
not c.isImplicit()
38+
)
39+
}
40+
}

0 commit comments

Comments
 (0)