Skip to content

Commit 0af44a7

Browse files
committed
C#: Changes to Type::{getQualifier,hasQualifiedName}
1 parent 8866e6c commit 0af44a7

File tree

25 files changed

+808
-718
lines changed

25 files changed

+808
-718
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
lgtm,codescanning
2+
* The following has changed in `Type::getQualifiedName`/`Type::hasQualifiedName`:
3+
- Type parameters now have the qualified name of the declaring generic as
4+
qualifier, and `<i>` as name, where `i` is the index of the type parameter.
5+
Example: in `class C<T> { }`, `T` has qualified name `C.<0>`.
6+
- Constructed types now use qualified names for type arguments. For example, the
7+
qualified name of `C<int>` is `C<System.Int32>`. This also includes array types
8+
and pointer types.
9+
- Nested types are now delimited by `+` instead of `.`. For example, the qualified
10+
name of `Inner` in `class Outer { class Inner { } }` is `Outer+Inner`.

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter {
185185
/** Gets the generic that defines this type parameter. */
186186
UnboundGeneric getGeneric() { type_parameters(this, _, result, _) }
187187

188+
final override predicate hasQualifiedName(string qualifier, string name) {
189+
qualifier = this.getGeneric().getQualifiedName() and
190+
name = "<" + this.getIndex().toString() + ">"
191+
}
192+
188193
override string getAPrimaryQlClass() { result = "TypeParameter" }
189194
}
190195

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ class Declaration extends DotNet::Declaration, Element, @declaration {
3434
* ```
3535
*/
3636
string getQualifiedNameWithTypes() {
37-
result = this.getDeclaringType().getQualifiedName() + "." + this.toStringWithTypes()
37+
exists(string qual |
38+
qual = this.getDeclaringType().getQualifiedName() and
39+
if this instanceof NestedType
40+
then result = qual + "+" + this.toStringWithTypes()
41+
else result = qual + "." + this.toStringWithTypes()
42+
)
3843
}
3944

4045
/**

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

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,50 @@ private predicate isObjectClass(Class c) { c instanceof ObjectType }
5555
* Either a value type (`ValueType`) or a reference type (`RefType`).
5656
*/
5757
class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_or_ref_type {
58+
/** Gets the name of this type without `<...>` brackets, in case it is a constructed type. */
59+
private string getNameWithoutBrackets() {
60+
exists(UnboundGenericType unbound, string name |
61+
unbound = this.(ConstructedType).getUnboundDeclaration() and
62+
name = unbound.getName() and
63+
result = name.prefix(name.length() - unbound.getNumberOfTypeParameters() - 1)
64+
)
65+
or
66+
not this instanceof ConstructedType and
67+
result = this.getName()
68+
}
69+
70+
language[monotonicAggregates]
71+
private string getQualifiedTypeArguments() {
72+
result =
73+
strictconcat(Type t, int i |
74+
t = this.(ConstructedType).getTypeArgument(i)
75+
|
76+
t.getQualifiedName(), "," order by i
77+
)
78+
}
79+
5880
/**
5981
* Holds if this type has the qualified name `qualifier`.`name`.
6082
*
6183
* For example the class `System.IO.IOException` has
6284
* `qualifier`=`System.IO` and `name`=`IOException`.
6385
*/
6486
override predicate hasQualifiedName(string qualifier, string name) {
65-
name = this.getName() and
66-
if exists(this.getDeclaringType())
67-
then qualifier = this.getDeclaringType().getQualifiedName()
68-
else qualifier = this.getNamespace().getQualifiedName()
87+
exists(string name0 |
88+
not this instanceof ConstructedType and
89+
name = name0
90+
or
91+
name = name0 + "<" + this.getQualifiedTypeArguments() + ">"
92+
|
93+
exists(string enclosing |
94+
this.getDeclaringType().hasQualifiedName(qualifier, enclosing) and
95+
name0 = enclosing + "+" + this.getNameWithoutBrackets()
96+
)
97+
or
98+
not exists(this.getDeclaringType()) and
99+
qualifier = this.getNamespace().getQualifiedName() and
100+
name0 = this.getNameWithoutBrackets()
101+
)
69102
}
70103

71104
/** Gets the namespace containing this type. */
@@ -994,6 +1027,13 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type {
9941027
not type_location(this, _) and
9951028
result = this.getElementType().getALocation()
9961029
}
1030+
1031+
final override predicate hasQualifiedName(string qualifier, string name) {
1032+
exists(Type elementType, string name0 |
1033+
elementType.hasQualifiedName(qualifier, name0) and
1034+
name = name0 + this.getDimensionString(elementType)
1035+
)
1036+
}
9971037
}
9981038

9991039
/**
@@ -1013,6 +1053,13 @@ class PointerType extends DotNet::PointerType, Type, @pointer_type {
10131053
override string toString() { result = DotNet::PointerType.super.toString() }
10141054

10151055
override string getAPrimaryQlClass() { result = "PointerType" }
1056+
1057+
final override predicate hasQualifiedName(string qualifier, string name) {
1058+
exists(string name0 |
1059+
this.getReferentType().hasQualifiedName(qualifier, name0) and
1060+
name = name0 + "*"
1061+
)
1062+
}
10161063
}
10171064

10181065
/**
@@ -1083,6 +1130,10 @@ class TupleType extends ValueType, @tuple_type {
10831130
override string getLabel() { result = getUnderlyingType().getLabel() }
10841131

10851132
override Type getChild(int i) { result = this.getUnderlyingType().getChild(i) }
1133+
1134+
final override predicate hasQualifiedName(string qualifier, string name) {
1135+
this.getUnderlyingType().hasQualifiedName(qualifier, name)
1136+
}
10861137
}
10871138

10881139
/**

csharp/ql/src/semmle/code/csharp/dataflow/ExternalFlow.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,13 +249,13 @@ module CsvValidation {
249249
not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and
250250
msg = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
251251
or
252-
not type.regexpMatch("[a-zA-Z0-9_<>\\.]+") and
252+
not type.regexpMatch("[a-zA-Z0-9_<>\\.\\+]+") and
253253
msg = "Dubious type \"" + type + "\" in " + pred + " model."
254254
or
255255
not name.regexpMatch("[a-zA-Z0-9_]*") and
256256
msg = "Dubious name \"" + name + "\" in " + pred + " model."
257257
or
258-
not signature.regexpMatch("|\\([a-zA-Z0-9_\\.<>,\\[\\]]*\\)") and
258+
not signature.regexpMatch("|\\([a-zA-Z0-9_<>\\.\\+,\\[\\]]*\\)") and
259259
msg = "Dubious signature \"" + signature + "\" in " + pred + " model."
260260
or
261261
not ext.regexpMatch("|Attribute") and
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
| ForeachExtension.cs:24:9:26:9 | foreach (... ... in ...) ... | Int32 | sync | Extensions | ForeachExtension.cs:8:34:8:49 | System.Collections.Generic.IEnumerator<Int32> | - | System.Collections.IEnumerator | - |
2-
| ForeachExtension.cs:29:9:31:9 | foreach (... ... in ...) ... | Int32 | async | Extensions | ForeachExtension.cs:9:39:9:59 | System.Collections.Generic.IAsyncEnumerator<Int32> | - | System.Collections.Generic.IAsyncEnumerator<Int32> | - |
3-
| ForeachExtension.cs:33:9:35:9 | foreach (... ... in ...) ... | Int32 | sync | Extensions | ForeachExtension.cs:10:36:10:48 | System.Collections.Generic.IEnumerator<Int32> | - | System.Collections.IEnumerator | - |
1+
| ForeachExtension.cs:24:9:26:9 | foreach (... ... in ...) ... | Int32 | sync | Extensions | ForeachExtension.cs:8:34:8:49 | System.Collections.Generic.IEnumerator<System.Int32> | - | System.Collections.IEnumerator | - |
2+
| ForeachExtension.cs:29:9:31:9 | foreach (... ... in ...) ... | Int32 | async | Extensions | ForeachExtension.cs:9:39:9:59 | System.Collections.Generic.IAsyncEnumerator<System.Int32> | - | System.Collections.Generic.IAsyncEnumerator<System.Int32> | - |
3+
| ForeachExtension.cs:33:9:35:9 | foreach (... ... in ...) ... | Int32 | sync | Extensions | ForeachExtension.cs:10:36:10:48 | System.Collections.Generic.IEnumerator<System.Int32> | - | System.Collections.IEnumerator | - |
44
| ForeachExtension.cs:37:9:39:9 | foreach (... ... in ...) ... | Int32 | sync | System.Collections.IEnumerable | - | System.Collections.IEnumerator | - | System.Collections.IEnumerator | - |

csharp/ql/test/library-tests/dataflow/external-models/steps.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ class SummaryModelTest extends SummaryModelCsv {
2020
"My.Qltest;C;false;StepPropertySetter;(System.Int32);;Argument[0];Property[My.Qltest.C.Property] of Argument[-1];value",
2121
"My.Qltest;C;false;StepElementGetter;();;Element of Argument[-1];ReturnValue;value",
2222
"My.Qltest;C;false;StepElementSetter;(System.Int32);;Argument[0];Element of Argument[-1];value",
23-
"My.Qltest.C;Generic<>;false;StepGeneric;(T);;Argument[0];ReturnValue;value",
24-
"My.Qltest.C;Generic<>;false;StepGeneric2;(S);;Argument[0];ReturnValue;value"
23+
"My.Qltest;C+Generic<>;false;StepGeneric;(My.Qltest.C+Generic<>.<0>);;Argument[0];ReturnValue;value",
24+
"My.Qltest;C+Generic<>;false;StepGeneric2;(My.Qltest.C+Generic<>.StepGeneric2.<0>);;Argument[0];ReturnValue;value"
2525
]
2626
}
2727
}

0 commit comments

Comments
 (0)