Skip to content

Commit 82c368e

Browse files
committed
C#: Sync XML.qll with other languages
1 parent 5a6a2e8 commit 82c368e

File tree

3 files changed

+111
-29
lines changed

3 files changed

+111
-29
lines changed

config/identical-files.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@
268268
],
269269
"XML": [
270270
"cpp/ql/src/semmle/code/cpp/XML.qll",
271+
"csharp/ql/src/semmle/code/csharp/XML.qll",
271272
"java/ql/src/semmle/code/xml/XML.qll",
272273
"javascript/ql/src/semmle/javascript/XML.qll",
273274
"python/ql/src/semmle/python/xml/XML.qll"

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

100644100755
Lines changed: 109 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,30 @@
22
* Provides classes and predicates for working with XML files and their content.
33
*/
44

5-
import semmle.code.csharp.Element
6-
import semmle.code.csharp.Location
5+
import semmle.files.FileSystem
76

87
/** An XML element that has a location. */
9-
class XMLLocatable extends @xmllocatable {
10-
XMLLocatable() {
11-
not this instanceof File // in the dbscheme
12-
}
13-
8+
abstract class XMLLocatable extends @xmllocatable {
149
/** Gets the source location for this element. */
15-
Location getALocation() { xmllocations(this, result) }
10+
Location getLocation() { xmllocations(this, result) }
1611

1712
/**
18-
* Whether this element has the specified location information,
19-
* including file path, start line, start column, end line and end column.
13+
* Holds if this element is at the specified location.
14+
* The location spans column `startcolumn` of line `startline` to
15+
* column `endcolumn` of line `endline` in file `filepath`.
16+
* For more information, see
17+
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
2018
*/
2119
predicate hasLocationInfo(
2220
string filepath, int startline, int startcolumn, int endline, int endcolumn
2321
) {
24-
exists(File f, Location l | l = this.getALocation() |
22+
exists(File f, Location l | l = this.getLocation() |
2523
locations_default(l, f, startline, startcolumn, endline, endcolumn) and
2624
filepath = f.getAbsolutePath()
2725
)
2826
}
2927

30-
/** Gets a printable representation of this element. */
28+
/** Gets a textual representation of this element. */
3129
abstract string toString();
3230
}
3331

@@ -36,6 +34,12 @@ class XMLLocatable extends @xmllocatable {
3634
* both of which can contain other elements.
3735
*/
3836
class XMLParent extends @xmlparent {
37+
XMLParent() {
38+
// explicitly restrict `this` to be either an `XMLElement` or an `XMLFile`;
39+
// the type `@xmlparent` currently also includes non-XML files
40+
this instanceof @xmlelement or xmlEncoding(this, _)
41+
}
42+
3943
/**
4044
* Gets a printable representation of this XML parent.
4145
* (Intended to be overridden in subclasses.)
@@ -69,7 +73,25 @@ class XMLParent extends @xmlparent {
6973
/** Gets the number of places in the body of this XML parent where text occurs. */
7074
int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) }
7175

72-
/** Append all the character sequences of this XML parent from left to right, separated by a space. */
76+
/**
77+
* DEPRECATED: Internal.
78+
*
79+
* Append the character sequences of this XML parent from left to right, separated by a space,
80+
* up to a specified (zero-based) index.
81+
*/
82+
deprecated string charsSetUpTo(int n) {
83+
n = 0 and xmlChars(_, result, this, 0, _, _)
84+
or
85+
n > 0 and
86+
exists(string chars | xmlChars(_, chars, this, n, _, _) |
87+
result = this.charsSetUpTo(n - 1) + " " + chars
88+
)
89+
}
90+
91+
/**
92+
* Gets the result of appending all the character sequences of this XML parent from
93+
* left to right, separated by a space.
94+
*/
7395
string allCharactersString() {
7496
result = concat(string chars, int pos |
7597
xmlChars(_, chars, this, pos, _, _)
@@ -93,15 +115,21 @@ class XMLFile extends XMLParent, File {
93115
override string toString() { result = XMLParent.super.toString() }
94116

95117
/** Gets the name of this XML file. */
96-
override string getName() { files(this, result, _, _, _) }
118+
override string getName() { result = File.super.getAbsolutePath() }
97119

98-
/** Gets the path of this XML file. */
99-
string getPath() { files(this, _, result, _, _) }
120+
/**
121+
* DEPRECATED: Use `getAbsolutePath()` instead.
122+
*
123+
* Gets the path of this XML file.
124+
*/
125+
deprecated string getPath() { result = getAbsolutePath() }
100126

101-
/** Gets the path of the folder that contains this XML file. */
102-
string getFolder() {
103-
result = this.getPath().substring(0, this.getPath().length() - this.getName().length())
104-
}
127+
/**
128+
* DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
129+
*
130+
* Gets the path of the folder that contains this XML file.
131+
*/
132+
deprecated string getFolder() { result = getParentContainer().getAbsolutePath() }
105133

106134
/** Gets the encoding of this XML file. */
107135
string getEncoding() { xmlEncoding(this, result) }
@@ -116,8 +144,18 @@ class XMLFile extends XMLParent, File {
116144
XMLDTD getADTD() { xmlDTDs(result, _, _, _, this) }
117145
}
118146

119-
/** A "Document Type Definition" of an XML file. */
120-
class XMLDTD extends XMLLocatable, @xmldtd {
147+
/**
148+
* An XML document type definition (DTD).
149+
*
150+
* Example:
151+
*
152+
* ```
153+
* <!ELEMENT person (firstName, lastName?)>
154+
* <!ELEMENT firstName (#PCDATA)>
155+
* <!ELEMENT lastName (#PCDATA)>
156+
* ```
157+
*/
158+
class XMLDTD extends @xmldtd {
121159
/** Gets the name of the root element of this DTD. */
122160
string getRoot() { xmlDTDs(this, result, _, _, _) }
123161

@@ -134,7 +172,7 @@ class XMLDTD extends XMLLocatable, @xmldtd {
134172
XMLParent getParent() { xmlDTDs(this, _, _, _, result) }
135173

136174
/** Gets a printable representation of this DTD. */
137-
override string toString() {
175+
string toString() {
138176
this.isPublic() and
139177
result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'"
140178
or
@@ -143,7 +181,17 @@ class XMLDTD extends XMLLocatable, @xmldtd {
143181
}
144182
}
145183

146-
/** An XML tag in an XML file. */
184+
/**
185+
* An XML element in an XML file.
186+
*
187+
* Example:
188+
*
189+
* ```
190+
* <manifest xmlns:android="http://schemas.android.com/apk/res/android"
191+
* package="com.example.exampleapp" android:versionCode="1">
192+
* </manifest>
193+
* ```
194+
*/
147195
class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
148196
/** Holds if this XML element has the given `name`. */
149197
predicate hasName(string name) { name = getName() }
@@ -188,7 +236,16 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
188236
override string toString() { result = XMLParent.super.toString() }
189237
}
190238

191-
/** An attribute that occurs inside an XML element. */
239+
/**
240+
* An attribute that occurs inside an XML element.
241+
*
242+
* Examples:
243+
*
244+
* ```
245+
* package="com.example.exampleapp"
246+
* android:versionCode="1"
247+
* ```
248+
*/
192249
class XMLAttribute extends @xmlattribute, XMLLocatable {
193250
/** Gets the name of this attribute. */
194251
string getName() { xmlAttrs(this, _, result, _, _, _) }
@@ -209,8 +266,16 @@ class XMLAttribute extends @xmlattribute, XMLLocatable {
209266
override string toString() { result = this.getName() + "=" + this.getValue() }
210267
}
211268

212-
/** A namespace used in an XML file */
213-
class XMLNamespace extends XMLLocatable, @xmlnamespace {
269+
/**
270+
* A namespace used in an XML file.
271+
*
272+
* Example:
273+
*
274+
* ```
275+
* xmlns:android="http://schemas.android.com/apk/res/android"
276+
* ```
277+
*/
278+
class XMLNamespace extends @xmlnamespace {
214279
/** Gets the prefix of this namespace. */
215280
string getPrefix() { xmlNs(this, result, _, _) }
216281

@@ -220,14 +285,23 @@ class XMLNamespace extends XMLLocatable, @xmlnamespace {
220285
/** Holds if this namespace has no prefix. */
221286
predicate isDefault() { this.getPrefix() = "" }
222287

223-
override string toString() {
288+
/** Gets a printable representation of this XML namespace. */
289+
string toString() {
224290
this.isDefault() and result = this.getURI()
225291
or
226292
not this.isDefault() and result = this.getPrefix() + ":" + this.getURI()
227293
}
228294
}
229295

230-
/** A comment of the form `<!-- ... -->` is an XML comment. */
296+
/**
297+
* A comment in an XML file.
298+
*
299+
* Example:
300+
*
301+
* ```
302+
* <!-- This is a comment. -->
303+
* ```
304+
*/
231305
class XMLComment extends @xmlcomment, XMLLocatable {
232306
/** Gets the text content of this XML comment. */
233307
string getText() { xmlComments(this, result, _, _) }
@@ -242,6 +316,12 @@ class XMLComment extends @xmlcomment, XMLLocatable {
242316
/**
243317
* A sequence of characters that occurs between opening and
244318
* closing tags of an XML element, excluding other elements.
319+
*
320+
* Example:
321+
*
322+
* ```
323+
* <content>This is a sequence of characters.</content>
324+
* ```
245325
*/
246326
class XMLCharacters extends @xmlcharacters, XMLLocatable {
247327
/** Gets the content of this character sequence. */
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/** Provides classes for working with files and folders. */
22

33
import semmle.code.csharp.File
4+
import semmle.code.csharp.Location

0 commit comments

Comments
 (0)