Skip to content

Commit 5a0db29

Browse files
committed
JS: Add DataFlow::Node.getLocation
1 parent 35a8e7c commit 5a0db29

22 files changed

+234
-97
lines changed

config/identical-files.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,6 @@
255255
"cpp/ql/lib/semmle/code/cpp/XML.qll",
256256
"csharp/ql/lib/semmle/code/csharp/XML.qll",
257257
"java/ql/lib/semmle/code/xml/XML.qll",
258-
"javascript/ql/lib/semmle/javascript/XML.qll",
259258
"python/ql/lib/semmle/python/xml/XML.qll"
260259
],
261260
"DuplicationProblems.inc.qhelp": [
@@ -372,4 +371,4 @@
372371
"python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ext.yml",
373372
"python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ext.yml"
374373
]
375-
}
374+
}

javascript/ql/lib/semmle/javascript/AST.qll

+6-10
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,27 @@ private import semmle.javascript.internal.CachedStages
2323
* ```
2424
*/
2525
class AstNode extends @ast_node, NodeInStmtContainer {
26-
override Location getLocation() { hasLocation(this, result) }
27-
2826
override File getFile() {
2927
result = this.getLocation().getFile() // Specialized for performance reasons
3028
}
3129

3230
/** Gets the first token belonging to this element. */
3331
Token getFirstToken() {
34-
exists(Location l1, Location l2 |
32+
exists(DbLocation l1, DbLocation l2, string filepath, int startline, int startcolumn |
3533
l1 = this.getLocation() and
3634
l2 = result.getLocation() and
37-
l1.getFile() = l2.getFile() and
38-
l1.getStartLine() = l2.getStartLine() and
39-
l1.getStartColumn() = l2.getStartColumn()
35+
l1.hasLocationInfo(filepath, startline, startcolumn, _, _) and
36+
l2.hasLocationInfo(filepath, startline, startcolumn, _, _)
4037
)
4138
}
4239

4340
/** Gets the last token belonging to this element. */
4441
Token getLastToken() {
45-
exists(Location l1, Location l2 |
42+
exists(DbLocation l1, DbLocation l2, string filepath, int endline, int endcolumn |
4643
l1 = this.getLocation() and
4744
l2 = result.getLocation() and
48-
l1.getFile() = l2.getFile() and
49-
l1.getEndLine() = l2.getEndLine() and
50-
l1.getEndColumn() = l2.getEndColumn()
45+
l1.hasLocationInfo(filepath, _, _, endline, endcolumn) and
46+
l2.hasLocationInfo(filepath, _, _, endline, endcolumn)
5147
) and
5248
// exclude empty EOF token
5349
not result instanceof EOFToken

javascript/ql/lib/semmle/javascript/CFG.qll

+1-3
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,7 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
356356
* A synthetic CFG node that does not correspond to a statement or expression;
357357
* examples include guard nodes and entry/exit nodes.
358358
*/
359-
class SyntheticControlFlowNode extends @synthetic_cfg_node, ControlFlowNode {
360-
override Location getLocation() { hasLocation(this, result) }
361-
}
359+
class SyntheticControlFlowNode extends @synthetic_cfg_node, ControlFlowNode { }
362360

363361
/** A synthetic CFG node marking the entry point of a function or toplevel script. */
364362
class ControlFlowEntryNode extends SyntheticControlFlowNode, @entry_node {

javascript/ql/lib/semmle/javascript/Comments.qll

-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ import javascript
1515
* </pre>
1616
*/
1717
class Comment extends @comment, Locatable {
18-
override Location getLocation() { hasLocation(this, result) }
19-
2018
/** Gets the toplevel element this comment belongs to. */
2119
TopLevel getTopLevel() { comments(this, _, result, _, _) }
2220

javascript/ql/lib/semmle/javascript/Errors.qll

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import javascript
44

55
/** An error encountered during extraction. */
66
abstract class Error extends Locatable {
7-
override Location getLocation() { hasLocation(this, result) }
8-
97
/** Gets the message associated with this error. */
108
abstract string getMessage();
119

javascript/ql/lib/semmle/javascript/Files.qll

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import javascript
44
private import NodeModuleResolutionImpl
55
private import codeql.util.FileSystem
6+
private import internal.Locations
67

78
private module FsInput implements InputSig {
89
abstract class ContainerBase extends @container {
@@ -83,7 +84,7 @@ class File extends Container, Impl::File {
8384
*
8485
* Note that files have special locations starting and ending at line zero, column zero.
8586
*/
86-
Location getLocation() { hasLocation(this, result) }
87+
DbLocation getLocation() { result = getLocatableLocation(this) }
8788

8889
/** Gets the number of lines in this file. */
8990
int getNumberOfLines() { result = sum(int loc | numlines(this, loc, _, _) | loc) }

javascript/ql/lib/semmle/javascript/HTML.qll

-8
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ module HTML {
4343
class Element extends Locatable, @xmlelement {
4444
Element() { exists(FileContainingHtml f | xmlElements(this, _, _, _, f)) }
4545

46-
override Location getLocation() { xmllocations(this, result) }
47-
4846
/**
4947
* Gets the name of this HTML element.
5048
*
@@ -122,8 +120,6 @@ module HTML {
122120
class Attribute extends Locatable, @xmlattribute {
123121
Attribute() { exists(FileContainingHtml f | xmlAttrs(this, _, _, _, _, f)) }
124122

125-
override Location getLocation() { xmllocations(this, result) }
126-
127123
/**
128124
* Gets the inline script of this attribute, if any.
129125
*/
@@ -326,8 +322,6 @@ module HTML {
326322
* Holds if this text node is inside a `CDATA` tag.
327323
*/
328324
predicate isCData() { xmlChars(this, _, _, _, 1, _) }
329-
330-
override Location getLocation() { xmllocations(this, result) }
331325
}
332326

333327
/**
@@ -349,7 +343,5 @@ module HTML {
349343
string getText() { result = this.toString().regexpCapture("(?s)<!--(.*)-->", 1) }
350344

351345
override string toString() { xmlComments(this, result, _, _) }
352-
353-
override Location getLocation() { xmllocations(this, result) }
354346
}
355347
}

javascript/ql/lib/semmle/javascript/JSDoc.qll

-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ private import semmle.javascript.internal.CachedStages
1818
* </pre>
1919
*/
2020
class JSDoc extends @jsdoc, Locatable {
21-
override Location getLocation() { hasLocation(this, result) }
22-
2321
/** Gets the description text of this JSDoc comment. */
2422
string getDescription() { jsdoc(this, result, _) }
2523

@@ -75,8 +73,6 @@ abstract class Documentable extends AstNode {
7573
* ```
7674
*/
7775
class JSDocTypeExprParent extends @jsdoc_type_expr_parent, Locatable {
78-
override Location getLocation() { hasLocation(this, result) }
79-
8076
/** Gets the JSDoc comment to which this element belongs. */
8177
JSDoc getJSDocComment() { none() }
8278
}

javascript/ql/lib/semmle/javascript/JSON.qll

+2-10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
import javascript
6+
private import semmle.javascript.internal.Locations
67

78
/**
89
* A JSON-encoded value, which may be a primitive value, an array or an object.
@@ -20,8 +21,6 @@ import javascript
2021
* ```
2122
*/
2223
class JsonValue extends @json_value, Locatable {
23-
override Location getLocation() { json_locations(this, result) }
24-
2524
/** Gets the parent value to which this value belongs, if any. */
2625
JsonValue getParent() { json(this, _, result, _, _) }
2726

@@ -34,12 +33,7 @@ class JsonValue extends @json_value, Locatable {
3433
override string toString() { json(this, _, _, _, result) }
3534

3635
/** Gets the JSON file containing this value. */
37-
File getJsonFile() {
38-
exists(Location loc |
39-
json_locations(this, loc) and
40-
result = loc.getFile()
41-
)
42-
}
36+
File getJsonFile() { result = getLocatableLocation(this).getFile() }
4337

4438
/** If this is an object, gets the value of property `name`. */
4539
JsonValue getPropValue(string name) { json_properties(this, name, result) }
@@ -172,7 +166,5 @@ class JsonObject extends @json_object, JsonValue {
172166
* An error reported by the JSON parser.
173167
*/
174168
class JsonParseError extends @json_parse_error, Error {
175-
override Location getLocation() { json_locations(this, result) }
176-
177169
override string getMessage() { json_errors(this, result) }
178170
}

javascript/ql/lib/semmle/javascript/Lines.qll

-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ import javascript
1414
* extracted with the `--extract-program-text` flag.
1515
*/
1616
class Line extends @line, Locatable {
17-
override Location getLocation() { hasLocation(this, result) }
18-
1917
/** Gets the toplevel element this line belongs to. */
2018
TopLevel getTopLevel() { lines(this, result, _, _) }
2119

javascript/ql/lib/semmle/javascript/Locations.qll

+21-32
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,41 @@
11
/** Provides classes for working with locations and program elements that have locations. */
22

33
import javascript
4+
private import internal.Locations
45

56
/**
67
* A location as given by a file, a start line, a start column,
78
* an end line, and an end column.
89
*
10+
* This class is restricted to locations created by the extractor.
11+
*
912
* For more information about locations see [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
1013
*/
11-
class Location extends @location {
14+
class DbLocation extends TDbLocation {
1215
/** Gets the file for this location. */
13-
File getFile() { locations_default(this, result, _, _, _, _) }
16+
File getFile() { dbLocationInfo(this, result, _, _, _, _) }
1417

1518
/** Gets the 1-based line number (inclusive) where this location starts. */
16-
int getStartLine() { locations_default(this, _, result, _, _, _) }
19+
int getStartLine() { dbLocationInfo(this, _, result, _, _, _) }
1720

1821
/** Gets the 1-based column number (inclusive) where this location starts. */
19-
int getStartColumn() { locations_default(this, _, _, result, _, _) }
22+
int getStartColumn() { dbLocationInfo(this, _, _, result, _, _) }
2023

2124
/** Gets the 1-based line number (inclusive) where this location ends. */
22-
int getEndLine() { locations_default(this, _, _, _, result, _) }
25+
int getEndLine() { dbLocationInfo(this, _, _, _, result, _) }
2326

2427
/** Gets the 1-based column number (inclusive) where this location ends. */
25-
int getEndColumn() { locations_default(this, _, _, _, _, result) }
28+
int getEndColumn() { dbLocationInfo(this, _, _, _, _, result) }
2629

2730
/** Gets the number of lines covered by this location. */
2831
int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 }
2932

3033
/** Holds if this location starts before location `that`. */
3134
pragma[inline]
32-
predicate startsBefore(Location that) {
35+
predicate startsBefore(DbLocation that) {
3336
exists(File f, int sl1, int sc1, int sl2, int sc2 |
34-
locations_default(this, f, sl1, sc1, _, _) and
35-
locations_default(that, f, sl2, sc2, _, _)
37+
dbLocationInfo(this, f, sl1, sc1, _, _) and
38+
dbLocationInfo(that, f, sl2, sc2, _, _)
3639
|
3740
sl1 < sl2
3841
or
@@ -42,10 +45,10 @@ class Location extends @location {
4245

4346
/** Holds if this location ends after location `that`. */
4447
pragma[inline]
45-
predicate endsAfter(Location that) {
48+
predicate endsAfter(DbLocation that) {
4649
exists(File f, int el1, int ec1, int el2, int ec2 |
47-
locations_default(this, f, _, _, el1, ec1) and
48-
locations_default(that, f, _, _, el2, ec2)
50+
dbLocationInfo(this, f, _, _, el1, ec1) and
51+
dbLocationInfo(that, f, _, _, el2, ec2)
4952
|
5053
el1 > el2
5154
or
@@ -57,10 +60,10 @@ class Location extends @location {
5760
* Holds if this location contains location `that`, meaning that it starts
5861
* before and ends after it.
5962
*/
60-
predicate contains(Location that) { this.startsBefore(that) and this.endsAfter(that) }
63+
predicate contains(DbLocation that) { this.startsBefore(that) and this.endsAfter(that) }
6164

6265
/** Holds if this location is empty. */
63-
predicate isEmpty() { exists(int l, int c | locations_default(this, _, l, c, l, c - 1)) }
66+
predicate isEmpty() { exists(int l, int c | dbLocationInfo(this, _, l, c, l, c - 1)) }
6467

6568
/** Gets a textual representation of this element. */
6669
string toString() { result = this.getFile().getBaseName() + ":" + this.getStartLine().toString() }
@@ -76,22 +79,21 @@ class Location extends @location {
7679
string filepath, int startline, int startcolumn, int endline, int endcolumn
7780
) {
7881
exists(File f |
79-
locations_default(this, f, startline, startcolumn, endline, endcolumn) and
82+
dbLocationInfo(this, f, startline, startcolumn, endline, endcolumn) and
8083
filepath = f.getAbsolutePath()
8184
)
8285
}
8386
}
8487

88+
final class Location = LocationImpl;
89+
8590
/** A program element with a location. */
8691
class Locatable extends @locatable {
8792
/** Gets the file this program element comes from. */
8893
File getFile() { result = this.getLocation().getFile() }
8994

9095
/** Gets this element's location. */
91-
Location getLocation() {
92-
// overridden by subclasses
93-
none()
94-
}
96+
final DbLocation getLocation() { result = getLocatableLocation(this) }
9597

9698
/**
9799
* Gets the line on which this element starts.
@@ -142,16 +144,3 @@ class Locatable extends @locatable {
142144
*/
143145
string getAPrimaryQlClass() { result = "???" }
144146
}
145-
146-
/**
147-
* A `File`, considered as a `Locatable`.
148-
*
149-
* For reasons of backwards compatibility, @file is a subtype of @locatable. This class exists to
150-
* provide an override of `Locatable.getLocation()` for @files, since it would otherwise default
151-
* to `none()`, which is unhelpful.
152-
*/
153-
private class FileLocatable extends File, Locatable {
154-
override Location getLocation() { result = File.super.getLocation() }
155-
156-
override string toString() { result = File.super.toString() }
157-
}

javascript/ql/lib/semmle/javascript/Regexp.qll

-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ class RegExpParent extends Locatable, @regexpparent { }
4343
* ```
4444
*/
4545
class RegExpTerm extends Locatable, @regexpterm {
46-
override Location getLocation() { hasLocation(this, result) }
47-
4846
/** Gets the `i`th child term of this term. */
4947
RegExpTerm getChild(int i) { regexpterm(result, _, this, i, _) }
5048

javascript/ql/lib/semmle/javascript/RestrictedLocations.qll

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class FirstLineOf extends Locatable {
2626
then endcolumn = xc
2727
else
2828
endcolumn =
29-
max(int c | any(Location l).hasLocationInfo(filepath, startline, _, startline, c))
29+
max(int c | any(DbLocation l).hasLocationInfo(filepath, startline, _, startline, c))
3030
)
3131
}
3232
}

javascript/ql/lib/semmle/javascript/Tokens.qll

-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ import javascript
1717
* ```
1818
*/
1919
class Token extends Locatable, @token {
20-
override Location getLocation() { hasLocation(this, result) }
21-
2220
/** Gets the toplevel syntactic structure to which this token belongs. */
2321
TopLevel getTopLevel() { tokeninfo(this, _, result, _, _) }
2422

javascript/ql/lib/semmle/javascript/Variables.qll

+2-2
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,9 @@ class LocalVariable extends Variable {
329329
* If the variable has one or more declarations, the location of the first declaration is used.
330330
* If the variable has no declaration, the entry point of its declaring container is used.
331331
*/
332-
Location getLocation() {
332+
DbLocation getLocation() {
333333
result =
334-
min(Location loc |
334+
min(DbLocation loc |
335335
loc = this.getADeclaration().getLocation()
336336
|
337337
loc order by loc.getStartLine(), loc.getStartColumn()

javascript/ql/lib/semmle/javascript/XML.qll

+3-5
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
*/
44

55
import semmle.files.FileSystem
6+
private import semmle.javascript.internal.Locations
67

78
private class TXmlLocatable =
89
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
910

1011
/** An XML element that has a location. */
1112
class XmlLocatable extends @xmllocatable, TXmlLocatable {
1213
/** Gets the source location for this element. */
13-
Location getLocation() { xmllocations(this, result) }
14+
DbLocation getLocation() { result = getLocatableLocation(this) }
1415

1516
/**
1617
* Holds if this element is at the specified location.
@@ -22,10 +23,7 @@ class XmlLocatable extends @xmllocatable, TXmlLocatable {
2223
predicate hasLocationInfo(
2324
string filepath, int startline, int startcolumn, int endline, int endcolumn
2425
) {
25-
exists(File f, Location l | l = this.getLocation() |
26-
locations_default(l, f, startline, startcolumn, endline, endcolumn) and
27-
filepath = f.getAbsolutePath()
28-
)
26+
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
2927
}
3028

3129
/** Gets a textual representation of this element. */

0 commit comments

Comments
 (0)