4
4
5
5
import Location
6
6
private import semmle.code.csharp.ExprOrStmtParent
7
- private import dotnet
8
7
private import commons.QualifiedName
9
8
10
9
/**
@@ -14,18 +13,64 @@ private import commons.QualifiedName
14
13
* (`NamespaceDeclaration`), a `using` directive (`UsingDirective`), or type
15
14
* parameter constraints (`TypeParameterConstraints`).
16
15
*/
17
- class Element extends DotNet:: Element , @element {
18
- override string toStringWithTypes ( ) { result = this .toString ( ) }
16
+ class Element extends @element {
17
+ /** Gets a textual representation of this element. */
18
+ cached
19
+ string toString ( ) { none ( ) }
20
+
21
+ /** Gets the file containing this element. */
22
+ final File getFile ( ) { result = this .getLocation ( ) .getFile ( ) }
23
+
24
+ /** Holds if this element is from source code. */
25
+ predicate fromSource ( ) { this .getFile ( ) .fromSource ( ) }
26
+
27
+ /** Holds if this element is from an assembly. */
28
+ predicate fromLibrary ( ) { this .getFile ( ) .fromLibrary ( ) }
29
+
30
+ /**
31
+ * Gets the "language" of this program element, as defined by the extension of the filename.
32
+ * For example, C# has language "cs", and Visual Basic has language "vb".
33
+ */
34
+ final string getLanguage ( ) { result = this .getLocation ( ) .getFile ( ) .getExtension ( ) }
35
+
36
+ /**
37
+ * Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
38
+ *
39
+ * If no primary class can be determined, the result is `"???"`.
40
+ */
41
+ final string getPrimaryQlClasses ( ) {
42
+ result = strictconcat ( this .getAPrimaryQlClass ( ) , "," )
43
+ or
44
+ not exists ( this .getAPrimaryQlClass ( ) ) and
45
+ result = "???"
46
+ }
47
+
48
+ /**
49
+ * Gets the name of a primary CodeQL class to which this element belongs.
50
+ *
51
+ * For most elements, this is simply the most precise syntactic category to
52
+ * which they belong; for example, `AddExpr` is a primary class, but
53
+ * `BinaryOperation` is not.
54
+ *
55
+ * If no primary classes match, this predicate has no result. If multiple
56
+ * primary classes match, this predicate can have multiple results.
57
+ *
58
+ * See also `getPrimaryQlClasses`, which is better to use in most cases.
59
+ */
60
+ string getAPrimaryQlClass ( ) { none ( ) }
61
+
62
+ /** Gets the full textual representation of this element, including type information. */
63
+ string toStringWithTypes ( ) { result = this .toString ( ) }
19
64
20
65
/**
21
66
* Gets the location of this element. Where an element has locations in
22
67
* source and assemblies, choose the source location. If there are multiple
23
68
* assembly locations, choose only one.
24
69
*/
25
- final override Location getLocation ( ) { result = bestLocation ( this ) }
70
+ final Location getLocation ( ) { result = bestLocation ( this ) }
26
71
27
72
/** Gets a location of this element, including sources and assemblies. */
28
- override Location getALocation ( ) { none ( ) }
73
+ Location getALocation ( ) { none ( ) }
29
74
30
75
/** Gets the parent of this element, if any. */
31
76
Element getParent ( ) { result .getAChild ( ) = this }
@@ -46,3 +91,96 @@ class Element extends DotNet::Element, @element {
46
91
*/
47
92
int getIndex ( ) { exists ( Element parent | parent .getChild ( result ) = this ) }
48
93
}
94
+
95
+ /** An element that has a name. */
96
+ class NamedElement extends Element , @named_element {
97
+ /** Gets the name of this element. */
98
+ cached
99
+ string getName ( ) { none ( ) }
100
+
101
+ /** Holds if this element has name 'name'. */
102
+ final predicate hasName ( string name ) { name = this .getName ( ) }
103
+
104
+ /**
105
+ * Gets the fully qualified name of this element, for example the
106
+ * fully qualified name of `M` on line 3 is `N.C.M` in
107
+ *
108
+ * ```csharp
109
+ * namespace N {
110
+ * class C {
111
+ * void M(int i, string s) { }
112
+ * }
113
+ * }
114
+ * ```
115
+ */
116
+ cached
117
+ deprecated final string getQualifiedName ( ) {
118
+ exists ( string qualifier , string name | this .hasQualifiedName ( qualifier , name ) |
119
+ if qualifier = "" then result = name else result = qualifier + "." + name
120
+ )
121
+ }
122
+
123
+ /**
124
+ * Gets the fully qualified name of this element, for example the
125
+ * fully qualified name of `M` on line 3 is `N.C.M` in
126
+ *
127
+ * ```csharp
128
+ * namespace N {
129
+ * class C {
130
+ * void M(int i, string s) { }
131
+ * }
132
+ * }
133
+ * ```
134
+ *
135
+ * Unbound generic types, such as `IList<T>`, are represented as
136
+ * ``System.Collections.Generic.IList`1``.
137
+ */
138
+ cached
139
+ final string getFullyQualifiedName ( ) {
140
+ exists ( string qualifier , string name | this .hasFullyQualifiedName ( qualifier , name ) |
141
+ if qualifier = "" then result = name else result = qualifier + "." + name
142
+ )
143
+ }
144
+
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
+
155
+ /** Holds if this element has the fully qualified name `qualifier`.`name`. */
156
+ cached
157
+ predicate hasFullyQualifiedName ( string qualifier , string name ) {
158
+ qualifier = "" and name = this .getName ( )
159
+ }
160
+
161
+ /** Gets a unique string label for this element. */
162
+ cached
163
+ string getLabel ( ) { none ( ) }
164
+
165
+ /** Holds if `other` has the same metadata handle in the same assembly. */
166
+ predicate matchesHandle ( NamedElement other ) {
167
+ exists ( Assembly asm , int handle |
168
+ metadata_handle ( this , asm , handle ) and
169
+ metadata_handle ( other , asm , handle )
170
+ )
171
+ }
172
+
173
+ /**
174
+ * Holds if this element was compiled from source code that is also present in the
175
+ * database. That is, this element corresponds to another element from source.
176
+ */
177
+ predicate compiledFromSource ( ) {
178
+ not this .fromSource ( ) and
179
+ exists ( NamedElement other | other != this |
180
+ this .matchesHandle ( other ) and
181
+ other .fromSource ( )
182
+ )
183
+ }
184
+
185
+ override string toString ( ) { result = this .getName ( ) }
186
+ }
0 commit comments