|
10 | 10 | * maintainability |
11 | 11 | */ |
12 | 12 |
|
13 | | -import csharp |
14 | | -import semmle.code.csharp.commons.Strings |
15 | | -import semmle.code.csharp.frameworks.System |
16 | | - |
17 | | -/** |
18 | | - * Holds if expression `e`, of type `t`, invokes `ToString()` either explicitly |
19 | | - * or implicitly. |
20 | | - */ |
21 | | -predicate invokesToString(Expr e, ValueOrRefType t) { |
22 | | - // Explicit invocation |
23 | | - exists(MethodCall mc | mc.getQualifier() = e | |
24 | | - mc.getTarget() instanceof ToStringMethod and |
25 | | - t = mc.getQualifier().getType() |
26 | | - ) |
27 | | - or |
28 | | - // Explicit or implicit invocation |
29 | | - e instanceof ImplicitToStringExpr and |
30 | | - t = e.stripCasts().getType() |
31 | | - or |
32 | | - // Implicit invocation via forwarder method |
33 | | - t = e.stripCasts().getType() and |
34 | | - not t instanceof StringType and |
35 | | - exists(AssignableDefinitions::ImplicitParameterDefinition def, Parameter p, ParameterRead pr | |
36 | | - e = p.getAnAssignedArgument() |
37 | | - | |
38 | | - def.getParameter() = p and |
39 | | - pr = def.getAReachableRead() and |
40 | | - pr.getAControlFlowNode().postDominates(p.getCallable().getEntryPoint()) and |
41 | | - invokesToString(pr, _) |
42 | | - ) |
43 | | -} |
44 | | - |
45 | | -/** |
46 | | - * Holds if `t`, or any sub type of `t`, inherits the default `ToString()` |
47 | | - * method from `System.Object` or `System.ValueType`. |
48 | | - */ |
49 | | -predicate alwaysDefaultToString(ValueOrRefType t) { |
50 | | - exists(ToStringMethod m | t.hasMethod(m) | |
51 | | - m.getDeclaringType() instanceof SystemObjectClass or |
52 | | - m.getDeclaringType() instanceof SystemValueTypeClass |
53 | | - ) and |
54 | | - not exists(RefType overriding | |
55 | | - overriding.getAMethod() instanceof ToStringMethod and |
56 | | - overriding.getABaseType+() = t |
57 | | - ) and |
58 | | - ((t.isAbstract() or t instanceof Interface) implies not t.isEffectivelyPublic()) |
59 | | -} |
60 | | - |
61 | | -class DefaultToStringType extends ValueOrRefType { |
62 | | - DefaultToStringType() { alwaysDefaultToString(this) } |
63 | | - |
64 | | - // A workaround for generating empty URLs for non-source locations, because qltest |
65 | | - // does not support non-source locations |
66 | | - override Location getLocation() { |
67 | | - result = super.getLocation() and |
68 | | - result instanceof SourceLocation |
69 | | - or |
70 | | - not super.getLocation() instanceof SourceLocation and |
71 | | - result instanceof EmptyLocation |
72 | | - } |
73 | | -} |
74 | | - |
75 | | -from Expr e, DefaultToStringType t |
76 | | -where invokesToString(e, t) |
77 | | -select e, |
78 | | - "Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing.", |
79 | | - t, t.getName() |
| 13 | +import DefaultToString |
0 commit comments