Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 01aa4ec

Browse files
authored
Merge pull request #1075 from hvitved/csharp/get-location-to-string
C#: Simplify dispatch hierarchy for `getLocation()` and `toString()`
2 parents 702fc80 + 089ad75 commit 01aa4ec

13 files changed

Lines changed: 119 additions & 107 deletions

File tree

csharp/ql/src/Useless code/DefaultToString.ql

Lines changed: 1 addition & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -10,70 +10,4 @@
1010
* maintainability
1111
*/
1212

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
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import csharp
2+
import semmle.code.csharp.commons.Strings
3+
import semmle.code.csharp.frameworks.System
4+
5+
/**
6+
* Holds if expression `e`, of type `t`, invokes `ToString()` either explicitly
7+
* or implicitly.
8+
*/
9+
predicate invokesToString(Expr e, ValueOrRefType t) {
10+
// Explicit invocation
11+
exists(MethodCall mc | mc.getQualifier() = e |
12+
mc.getTarget() instanceof ToStringMethod and
13+
t = mc.getQualifier().getType()
14+
)
15+
or
16+
// Explicit or implicit invocation
17+
e instanceof ImplicitToStringExpr and
18+
t = e.stripCasts().getType()
19+
or
20+
// Implicit invocation via forwarder method
21+
t = e.stripCasts().getType() and
22+
not t instanceof StringType and
23+
exists(AssignableDefinitions::ImplicitParameterDefinition def, Parameter p, ParameterRead pr |
24+
e = p.getAnAssignedArgument()
25+
|
26+
def.getParameter() = p and
27+
pr = def.getAReachableRead() and
28+
pr.getAControlFlowNode().postDominates(p.getCallable().getEntryPoint()) and
29+
invokesToString(pr, _)
30+
)
31+
}
32+
33+
/**
34+
* Holds if `t`, or any sub type of `t`, inherits the default `ToString()`
35+
* method from `System.Object` or `System.ValueType`.
36+
*/
37+
predicate alwaysDefaultToString(ValueOrRefType t) {
38+
exists(ToStringMethod m | t.hasMethod(m) |
39+
m.getDeclaringType() instanceof SystemObjectClass or
40+
m.getDeclaringType() instanceof SystemValueTypeClass
41+
) and
42+
not exists(RefType overriding |
43+
overriding.getAMethod() instanceof ToStringMethod and
44+
overriding.getABaseType+() = t
45+
) and
46+
((t.isAbstract() or t instanceof Interface) implies not t.isEffectivelyPublic())
47+
}
48+
49+
class DefaultToStringType extends ValueOrRefType {
50+
DefaultToStringType() { alwaysDefaultToString(this) }
51+
}
52+
53+
query predicate problems(Expr e, string s, DefaultToStringType t, string name) {
54+
invokesToString(e, t) and
55+
s = "Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing." and
56+
name = t.getName()
57+
}

csharp/ql/src/external/ExternalArtifact.qll

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
import csharp
22

3-
class ExternalDefect extends @externalDefect, Element {
3+
class ExternalElement extends @external_element {
4+
/** Gets a textual representation of this element. */
5+
string toString() { none() }
6+
7+
/** Gets the location of this element. */
8+
Location getLocation() { none() }
9+
10+
/** Gets the file containing this element. */
11+
File getFile() { result = getLocation().getFile() }
12+
}
13+
14+
class ExternalDefect extends ExternalElement, @externalDefect {
415
string getQueryPath() {
516
exists(string path |
617
externalDefects(this, path, _, _, _) and
@@ -19,7 +30,7 @@ class ExternalDefect extends @externalDefect, Element {
1930
}
2031
}
2132

22-
class ExternalMetric extends @externalMetric, Element {
33+
class ExternalMetric extends ExternalElement, @externalMetric {
2334
string getQueryPath() { externalMetrics(this, result, _, _) }
2435

2536
float getValue() { externalMetrics(this, _, _, result) }
@@ -29,7 +40,7 @@ class ExternalMetric extends @externalMetric, Element {
2940
override string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getValue() }
3041
}
3142

32-
class ExternalData extends @externalDataElement {
43+
class ExternalData extends ExternalElement, @externalDataElement {
3344
string getDataPath() { externalData(this, result, _, _) }
3445

3546
string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") }
@@ -44,7 +55,7 @@ class ExternalData extends @externalDataElement {
4455

4556
date getFieldAsDate(int index) { result = getField(index).toDate() }
4657

47-
string toString() { result = getQueryPath() + ": " + buildTupleString(0) }
58+
override string toString() { result = getQueryPath() + ": " + buildTupleString(0) }
4859

4960
private string buildTupleString(int start) {
5061
start = getNumFields() - 1 and result = getField(start)

csharp/ql/src/semmle/code/csharp/Attribute.qll

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,18 @@ class Attributable extends @attributable {
1818
/** Gets a textual representation of this element. */
1919
string toString() { none() }
2020

21-
/** Gets the location of this element, if any. */
22-
Location getLocation() { none() }
21+
/**
22+
* Holds if this element is at the specified location.
23+
* The location spans column `startcolumn` of line `startline` to
24+
* column `endcolumn` of line `endline` in file `filepath`.
25+
* For more information, see
26+
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
27+
*/
28+
predicate hasLocationInfo(
29+
string filepath, int startline, int startcolumn, int endline, int endcolumn
30+
) {
31+
this.(Element).getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
32+
}
2333
}
2434

2535
/**

csharp/ql/src/semmle/code/csharp/Callable.qll

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,6 @@ class Method extends Callable, Virtualizable, Attributable, @method {
283283

284284
override string toString() { result = Callable.super.toString() }
285285

286-
override Location getLocation() { result = Callable.super.getLocation() }
287-
288286
override Parameter getRawParameter(int i) {
289287
if this.isStatic() then result = this.getParameter(i) else result = this.getParameter(i - 1)
290288
}
@@ -354,8 +352,6 @@ class Constructor extends DotNet::Constructor, Callable, Member, Attributable, @
354352

355353
override string toString() { result = Callable.super.toString() }
356354

357-
override Location getLocation() { result = Callable.super.getLocation() }
358-
359355
override Parameter getRawParameter(int i) {
360356
if this.isStatic() then result = this.getParameter(i) else result = this.getParameter(i - 1)
361357
}
@@ -419,8 +415,6 @@ class Destructor extends DotNet::Destructor, Callable, Member, Attributable, @de
419415
override Location getALocation() { destructor_location(this, result) }
420416

421417
override string toString() { result = Callable.super.toString() }
422-
423-
override Location getLocation() { result = Callable.super.getLocation() }
424418
}
425419

426420
/**
@@ -447,8 +441,6 @@ class Operator extends Callable, Member, Attributable, @operator {
447441

448442
override string toString() { result = Callable.super.toString() }
449443

450-
override Location getLocation() { result = Callable.super.getLocation() }
451-
452444
override Parameter getRawParameter(int i) { result = getParameter(i) }
453445
}
454446

csharp/ql/src/semmle/code/csharp/Element.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Element extends DotNet::Element, @element {
2222
* Where an element has multiple locations (for example a source file and an assembly),
2323
* gets only the source location.
2424
*/
25-
override Location getLocation() { result = ExprOrStmtParentCached::bestLocation(this) }
25+
final override Location getLocation() { result = ExprOrStmtParentCached::bestLocation(this) }
2626

2727
/** Gets a location of this element, including sources and assemblies. */
2828
override Location getALocation() { none() }

csharp/ql/src/semmle/code/csharp/Property.qll

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ class DeclarationWithAccessors extends AssignableMember, Virtualizable, Attribut
4343
override Type getType() { none() }
4444

4545
override string toString() { result = AssignableMember.super.toString() }
46-
47-
override Location getLocation() { result = AssignableMember.super.getLocation() }
4846
}
4947

5048
/**
@@ -360,8 +358,6 @@ class Accessor extends Callable, Modifiable, Attributable, @callable_accessor {
360358
override Location getALocation() { accessor_location(this, result) }
361359

362360
override string toString() { result = getName() }
363-
364-
override Location getLocation() { result = Callable.super.getLocation() }
365361
}
366362

367363
/**

csharp/ql/src/semmle/code/csharp/Type.qll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,6 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_
362362
}
363363

364364
override string toString() { result = Type.super.toString() }
365-
366-
override Location getLocation() { result = Type.super.getLocation() }
367365
}
368366

369367
/**

csharp/ql/src/semmle/code/csharp/Variable.qll

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,6 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top
222222

223223
override string toString() { result = this.getName() }
224224

225-
override Location getLocation() { result = LocalScopeVariable.super.getLocation() }
226-
227225
/**
228226
* Gets the default value of this parameter, if any. For example, the
229227
* default value of `numberOfTries` is `3` in
@@ -400,8 +398,6 @@ class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent
400398
override FieldAccess getAnAccess() { result = Variable.super.getAnAccess() }
401399

402400
override string toString() { result = Variable.super.toString() }
403-
404-
override Location getLocation() { result = Variable.super.getLocation() }
405401
}
406402

407403
/**

csharp/ql/src/semmle/code/csharp/exprs/Expr.qll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ private import dotnet
3939
* (`QualifiableExpr`), or a literal (`Literal`).
4040
*/
4141
class Expr extends DotNet::Expr, ControlFlowElement, @expr {
42-
override string toString() { result = "Expression" }
43-
4442
override Location getALocation() { expr_location(this, result) }
4543

4644
/** Gets the type of this expression. */
@@ -717,3 +715,7 @@ class RefExpr extends Expr, @ref_expr {
717715
class DiscardExpr extends Expr, @discard_expr {
718716
override string toString() { result = "_" }
719717
}
718+
719+
private class UnknownExpr extends Expr, @unknown_expr {
720+
override string toString() { result = "Expression" }
721+
}

0 commit comments

Comments
 (0)