Skip to content

Commit bd1de17

Browse files
authored
Merge pull request #15887 from michaelnebel/csharp/qualifiedname
C#: Fully qualified name.
2 parents 7b2dc32 + 10d96ee commit bd1de17

File tree

23 files changed

+107
-155
lines changed

23 files changed

+107
-155
lines changed

csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import csharp
22

33
from Class c
44
where c.fromSource()
5-
select c, c.getBaseClass().getFullyQualifiedName()
5+
select c, c.getBaseClass().getFullyQualifiedNameDebug()

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

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ class NamedElement extends Element, @named_element {
102102
final predicate hasName(string name) { name = this.getName() }
103103

104104
/**
105+
* DEPRECATED: Use `hasFullyQualifiedName` instead.
106+
*
105107
* Gets the fully qualified name of this element, for example the
106108
* fully qualified name of `M` on line 3 is `N.C.M` in
107109
*
@@ -112,15 +114,23 @@ class NamedElement extends Element, @named_element {
112114
* }
113115
* }
114116
* ```
117+
*
118+
* Unbound generic types, such as `IList<T>`, are represented as
119+
* ``System.Collections.Generic.IList`1``.
115120
*/
116-
cached
117-
deprecated final string getQualifiedName() {
118-
exists(string qualifier, string name | this.hasQualifiedName(qualifier, name) |
121+
deprecated final string getFullyQualifiedName() {
122+
exists(string qualifier, string name | this.hasFullyQualifiedName(qualifier, name) |
119123
if qualifier = "" then result = name else result = qualifier + "." + name
120124
)
121125
}
122126

123127
/**
128+
* INTERNAL: Do not use.
129+
*
130+
* This is intended for DEBUG ONLY.
131+
* Constructing the fully qualified name for all elements in a large codebase
132+
* puts severe stress on the string pool.
133+
*
124134
* Gets the fully qualified name of this element, for example the
125135
* fully qualified name of `M` on line 3 is `N.C.M` in
126136
*
@@ -135,23 +145,14 @@ class NamedElement extends Element, @named_element {
135145
* Unbound generic types, such as `IList<T>`, are represented as
136146
* ``System.Collections.Generic.IList`1``.
137147
*/
138-
cached
139-
final string getFullyQualifiedName() {
148+
bindingset[this]
149+
pragma[inline_late]
150+
final string getFullyQualifiedNameDebug() {
140151
exists(string qualifier, string name | this.hasFullyQualifiedName(qualifier, name) |
141152
if qualifier = "" then result = name else result = qualifier + "." + name
142153
)
143154
}
144155

145-
/**
146-
* DEPRECATED: Use `hasFullyQualifiedName` instead.
147-
*
148-
* Holds if this element has the qualified name `qualifier`.`name`.
149-
*/
150-
cached
151-
deprecated predicate hasQualifiedName(string qualifier, string name) {
152-
qualifier = "" and name = this.getName()
153-
}
154-
155156
/** Holds if this element has the fully qualified name `qualifier`.`name`. */
156157
cached
157158
predicate hasFullyQualifiedName(string qualifier, string name) {

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

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,11 @@ class Declaration extends NamedElement, @declaration {
7171

7272
override string toString() { result = this.getName() }
7373

74-
deprecated override predicate hasQualifiedName(string qualifier, string name) {
75-
QualifiedName<QualifiedNameInput>::hasQualifiedName(this, qualifier, name)
76-
}
77-
7874
override predicate hasFullyQualifiedName(string qualifier, string name) {
7975
QualifiedName<FullyQualifiedNameInput>::hasQualifiedName(this, qualifier, name)
8076
}
8177

8278
/**
83-
* DEPRECATED: Use `getFullyQualifiedNameWithTypes` instead.
84-
*
8579
* Gets the fully qualified name of this declaration, including types, for example
8680
* the fully qualified name with types of `M` on line 3 is `N.C.M(int, string)` in
8781
*
@@ -93,33 +87,13 @@ class Declaration extends NamedElement, @declaration {
9387
* }
9488
* ```
9589
*/
96-
deprecated string getQualifiedNameWithTypes() {
97-
exists(string qual |
98-
qual = this.getDeclaringType().getQualifiedName() and
90+
deprecated string getFullyQualifiedNameWithTypes() {
91+
exists(string fullqual, string qual, string name |
92+
this.getDeclaringType().hasFullyQualifiedName(qual, name) and
93+
fullqual = getQualifiedName(qual, name) and
9994
if this instanceof NestedType
100-
then result = qual + "+" + this.toStringWithTypes()
101-
else result = qual + "." + this.toStringWithTypes()
102-
)
103-
}
104-
105-
/**
106-
* Gets the fully qualified name of this declaration, including types, for example
107-
* the fully qualified name with types of `M` on line 3 is `N.C.M(int, string)` in
108-
*
109-
* ```csharp
110-
* namespace N {
111-
* class C {
112-
* void M(int i, string s) { }
113-
* }
114-
* }
115-
* ```
116-
*/
117-
string getFullyQualifiedNameWithTypes() {
118-
exists(string qual |
119-
qual = this.getDeclaringType().getFullyQualifiedName() and
120-
if this instanceof NestedType
121-
then result = qual + "+" + this.toStringWithTypes()
122-
else result = qual + "." + this.toStringWithTypes()
95+
then result = fullqual + "+" + this.toStringWithTypes()
96+
else result = fullqual + "." + this.toStringWithTypes()
12397
)
12498
}
12599

@@ -263,17 +237,6 @@ class Member extends Modifiable, @member {
263237
/** Gets an access to this member. */
264238
MemberAccess getAnAccess() { result.getTarget() = this }
265239

266-
/**
267-
* DEPRECATED: Use `hasFullyQualifiedName` instead.
268-
*
269-
* Holds if this member has name `name` and is defined in type `type`
270-
* with namespace `namespace`.
271-
*/
272-
cached
273-
deprecated final predicate hasQualifiedName(string namespace, string type, string name) {
274-
QualifiedName<QualifiedNameInput>::hasQualifiedName(this, namespace, type, name)
275-
}
276-
277240
/**
278241
* Holds if this member has name `name` and is defined in type `type`
279242
* with namespace `namespace`.

csharp/ql/lib/semmle/code/csharp/Namespace.qll

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,6 @@ class Namespace extends TypeContainer, Declaration, @namespace {
3838
parent_namespace(result, this)
3939
}
4040

41-
/**
42-
* Holds if this namespace has the qualified name `qualifier`.`name`.
43-
*
44-
* For example if the qualified name is `System.Collections.Generic`, then
45-
* `qualifier`=`System.Collections` and `name`=`Generic`.
46-
*/
47-
deprecated override predicate hasQualifiedName(string qualifier, string name) {
48-
namespaceHasQualifiedName(this, qualifier, name)
49-
}
50-
5141
/**
5242
* Holds if this namespace has the qualified name `qualifier`.`name`.
5343
*

csharp/ql/lib/semmle/code/csharp/commons/QualifiedName.qll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,28 @@ predicate splitQualifiedName(string qualifiedName, string qualifier, string name
219219
name = qualifiedName
220220
)
221221
}
222+
223+
/**
224+
* INTERNAL: Do not use.
225+
*
226+
* Gets the fully qualified name of this declaration, including types, for example
227+
* the fully qualified name with types of `M` on line 3 is `N.C.M(int, string)` in
228+
*
229+
* ```csharp
230+
* namespace N {
231+
* class C {
232+
* void M(int i, string s) { }
233+
* }
234+
* }
235+
* ```
236+
*/
237+
bindingset[d]
238+
string getFullyQualifiedNameWithTypes(Declaration d) {
239+
exists(string fullqual, string qual, string name |
240+
d.getDeclaringType().hasFullyQualifiedName(qual, name) and
241+
fullqual = getQualifiedName(qual, name) and
242+
if d instanceof NestedType
243+
then result = fullqual + "+" + d.toStringWithTypes()
244+
else result = fullqual + "." + d.toStringWithTypes()
245+
)
246+
}

csharp/ql/lib/semmle/code/csharp/dataflow/SSA.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ module Ssa {
120120
result = prefix + "." + this.getAssignable()
121121
|
122122
if f.(Modifiable).isStatic()
123-
then prefix = f.getDeclaringType().getFullyQualifiedName()
123+
then prefix = f.getDeclaringType().getName()
124124
else prefix = "this"
125125
)
126126
}

csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
private import csharp
6+
private import semmle.code.csharp.commons.QualifiedName
67
private import semmle.code.csharp.frameworks.system.linq.Expressions
78
private import codeql.dataflow.internal.FlowSummaryImpl
89
private import codeql.dataflow.internal.AccessPathSyntax as AccessPath
@@ -42,10 +43,18 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CsharpDataFlow>
4243
string encodeContent(ContentSet c, string arg) {
4344
c = TElementContent() and result = "Element" and arg = ""
4445
or
45-
exists(Field f | c = TFieldContent(f) and result = "Field" and arg = f.getFullyQualifiedName())
46+
exists(Field f, string qualifier, string name |
47+
c = TFieldContent(f) and
48+
f.hasFullyQualifiedName(qualifier, name) and
49+
arg = getQualifiedName(qualifier, name) and
50+
result = "Field"
51+
)
4652
or
47-
exists(Property p |
48-
c = TPropertyContent(p) and result = "Property" and arg = p.getFullyQualifiedName()
53+
exists(Property p, string qualifier, string name |
54+
c = TPropertyContent(p) and
55+
p.hasFullyQualifiedName(qualifier, name) and
56+
arg = getQualifiedName(qualifier, name) and
57+
result = "Property"
4958
)
5059
or
5160
exists(SyntheticField f |

csharp/ql/lib/semmle/code/csharp/security/dataflow/ExternalAPIsQuery.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,13 +139,13 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi {
139139

140140
/** Gets a textual representation of this element. */
141141
string toString() {
142-
exists(Callable m, int index, string indexString |
142+
exists(Callable m, int index, string indexString, string qualifier, string name |
143143
if index = -1 then indexString = "qualifier" else indexString = "param " + index
144144
|
145145
this = TExternalApiParameter(m, index) and
146+
m.getDeclaringType().hasFullyQualifiedName(qualifier, name) and
146147
result =
147-
m.getDeclaringType().getFullyQualifiedName() + "." + m.toStringWithTypes() + " [" +
148-
indexString + "]"
148+
getQualifiedName(qualifier, name) + "." + m.toStringWithTypes() + " [" + indexString + "]"
149149
)
150150
}
151151
}
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import csharp
2-
import semmle.code.csharp.commons.QualifiedName
32

4-
from Attributable element, Attribute attribute, string qualifier, string name
3+
from Attributable element, Attribute attribute
54
where
65
attribute = element.getAnAttribute() and
7-
(attribute.fromSource() or element.(Assembly).getName() in ["attributes", "Assembly1"]) and
8-
attribute.getType().hasFullyQualifiedName(qualifier, name)
9-
select element, attribute, getQualifiedName(qualifier, name)
6+
(attribute.fromSource() or element.(Assembly).getName() in ["attributes", "Assembly1"])
7+
select element, attribute, attribute.getType().getFullyQualifiedNameDebug()

csharp/ql/test/library-tests/constructors/Destructors1.ql

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
*/
44

55
import csharp
6-
import semmle.code.csharp.commons.QualifiedName
76

87
from Destructor c, string qualifier, string name
98
where
109
c.getDeclaringType().hasFullyQualifiedName(qualifier, name) and
1110
qualifier = "Constructors" and
1211
name = "Class"
13-
select c, c.getDeclaringType().getFullyQualifiedName()
12+
select c, c.getDeclaringType().getFullyQualifiedNameDebug()

csharp/ql/test/library-tests/csharp11/fileScoped.ql

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import csharp
2-
private import semmle.code.csharp.commons.QualifiedName
32

43
private predicate isInteresting(Type t) {
54
(
@@ -20,10 +19,7 @@ query predicate typemodifiers(Type t, string modifier) {
2019

2120
query predicate qualifiedtypes(Type t, string qualifiedName) {
2221
isInteresting(t) and
23-
exists(string qualifier, string name |
24-
t.hasFullyQualifiedName(qualifier, name) and
25-
qualifiedName = getQualifiedName(qualifier, name)
26-
)
22+
qualifiedName = t.getFullyQualifiedNameDebug()
2723
}
2824

2925
query predicate filetypes(Type t) {
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import csharp
2-
import semmle.code.csharp.commons.QualifiedName
32

4-
from LocalVariable v1, LocalVariable v2, Type t, string qualifier, string name
3+
from LocalVariable v1, LocalVariable v2, Type t
54
where
65
v1.getFile().getStem() = "NativeInt" and
76
v2.getFile().getStem() = "NativeInt" and
87
t = v1.getType() and
98
t = v2.getType() and
10-
t.hasFullyQualifiedName(qualifier, name) and
119
v1 != v2
12-
select v1, v2, getQualifiedName(qualifier, name)
10+
select v1, v2, t.getFullyQualifiedNameDebug()
Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
import csharp
2-
import semmle.code.csharp.commons.QualifiedName
32

4-
from
5-
Method m, Method overrider, string mnamespace, string mtype, string mname, string onamespace,
6-
string otype, string oname
3+
from Method m, Method overrider
74
where
85
m.getAnOverrider() = overrider and
9-
m.getFile().getStem() = "CovariantReturn" and
10-
m.hasFullyQualifiedName(mnamespace, mtype, mname) and
11-
overrider.hasFullyQualifiedName(onamespace, otype, oname)
12-
select getQualifiedName(mnamespace, mtype, mname), m.getReturnType().toString(),
13-
getQualifiedName(onamespace, otype, oname), overrider.getReturnType().toString()
6+
m.getFile().getStem() = "CovariantReturn"
7+
select m.getFullyQualifiedNameDebug(), m.getReturnType().toString(),
8+
overrider.getFullyQualifiedNameDebug(), overrider.getReturnType().toString()
Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import csharp
2-
import semmle.code.csharp.commons.QualifiedName
32

43
private string getLocation(Member m) {
54
if m.fromSource() then result = m.getALocation().(SourceLocation).toString() else result = "-"
@@ -9,13 +8,9 @@ private string getIsAsync(ForeachStmt f) {
98
if f.isAsync() then result = "async" else result = "sync"
109
}
1110

12-
from
13-
ForeachStmt f, string qualifier1, string type1, string qualifier2, string type2,
14-
string qualifier3, string type3
15-
where
16-
f.getGetEnumerator().getDeclaringType().hasFullyQualifiedName(qualifier1, type1) and
17-
f.getCurrent().getDeclaringType().hasFullyQualifiedName(qualifier2, type2) and
18-
f.getMoveNext().getDeclaringType().hasFullyQualifiedName(qualifier3, type3)
19-
select f, f.getElementType().toString(), getIsAsync(f), getQualifiedName(qualifier1, type1),
20-
getLocation(f.getGetEnumerator()), getQualifiedName(qualifier2, type2),
21-
getLocation(f.getCurrent()), getQualifiedName(qualifier3, type3), getLocation(f.getMoveNext())
11+
from ForeachStmt f
12+
select f, f.getElementType().toString(), getIsAsync(f),
13+
f.getGetEnumerator().getDeclaringType().getFullyQualifiedNameDebug(),
14+
getLocation(f.getGetEnumerator()), f.getCurrent().getDeclaringType().getFullyQualifiedNameDebug(),
15+
getLocation(f.getCurrent()), f.getMoveNext().getDeclaringType().getFullyQualifiedNameDebug(),
16+
getLocation(f.getMoveNext())

csharp/ql/test/library-tests/csharp9/record.ql

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,10 @@ query predicate records(RecordClass t, string i, RecordCloneMethod clone) {
77
t.fromSource()
88
}
99

10-
private string getMemberName(Member m) {
11-
exists(string qualifier, string name |
12-
m.getDeclaringType().hasFullyQualifiedName(qualifier, name)
13-
|
14-
result = getQualifiedName(qualifier, name) + "." + m.toStringWithTypes()
15-
)
16-
}
17-
1810
query predicate members(RecordClass t, string ms, string l) {
1911
t.fromSource() and
2012
exists(Member m | t.hasMember(m) |
21-
ms = getMemberName(m) and
13+
ms = getFullyQualifiedNameWithTypes(m) and
2214
if m.fromSource() then l = m.getLocation().toString() else l = "no location"
2315
)
2416
}

0 commit comments

Comments
 (0)