Skip to content

Commit 7c3a6f8

Browse files
committed
Go: Refactor Location implementation
1 parent b08f535 commit 7c3a6f8

File tree

3 files changed

+107
-135
lines changed

3 files changed

+107
-135
lines changed

go/ql/lib/semmle/go/Locations.qll

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,21 @@
33
import go
44
private import internal.Locations
55

6+
private module DbLocationInput implements LocationClassInputSig {
7+
class Base = TDbLocation;
8+
9+
predicate locationInfo(
10+
Base b, string filepath, int startline, int startcolumn, int endline, int endcolumn
11+
) {
12+
exists(File f |
13+
dbLocationInfo(b, f, startline, startcolumn, endline, endcolumn) and
14+
filepath = f.getAbsolutePath()
15+
)
16+
}
17+
18+
File getFile(Base b) { dbLocationInfo(b, result, _, _, _, _) }
19+
}
20+
621
/**
722
* A location as given by a file, a start line, a start column,
823
* an end line, and an end column.
@@ -11,51 +26,21 @@ private import internal.Locations
1126
*
1227
* For more information about locations see [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
1328
*/
14-
class DbLocation extends TDbLocation {
15-
/** Gets the file for this location. */
16-
File getFile() { dbLocationInfo(this, result, _, _, _, _) }
17-
18-
/** Gets the 1-based line number (inclusive) where this location starts. */
19-
int getStartLine() { dbLocationInfo(this, _, result, _, _, _) }
20-
21-
/** Gets the 1-based column number (inclusive) where this location starts. */
22-
int getStartColumn() { dbLocationInfo(this, _, _, result, _, _) }
23-
24-
/** Gets the 1-based line number (inclusive) where this location ends. */
25-
int getEndLine() { dbLocationInfo(this, _, _, _, result, _) }
29+
class DbLocation = LocationClass<DbLocationInput>::Location;
2630

27-
/** Gets the 1-based column number (inclusive) where this location ends. */
28-
int getEndColumn() { dbLocationInfo(this, _, _, _, _, result) }
29-
30-
/** Gets the number of lines covered by this location. */
31-
int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 }
32-
33-
/** Gets a textual representation of this element. */
34-
string toString() {
35-
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
36-
this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
37-
result = filepath + "@" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
38-
)
39-
}
31+
private module LocationInput implements LocationClassInputSig {
32+
class Base = TLocation;
4033

41-
/**
42-
* Holds if this element is at the specified location.
43-
* The location spans column `startcolumn` of line `startline` to
44-
* column `endcolumn` of line `endline` in file `filepath`.
45-
* For more information, see
46-
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
47-
*/
48-
predicate hasLocationInfo(
49-
string filepath, int startline, int startcolumn, int endline, int endcolumn
34+
predicate locationInfo(
35+
Base b, string filepath, int startline, int startcolumn, int endline, int endcolumn
5036
) {
51-
exists(File f |
52-
dbLocationInfo(this, f, startline, startcolumn, endline, endcolumn) and
53-
filepath = f.getAbsolutePath()
54-
)
37+
dataFlowNodeLocationInfo(b, filepath, startline, startcolumn, endline, endcolumn)
5538
}
39+
40+
File getFile(Base b) { dataFlowNodeLocationInfo(b, result.getAbsolutePath(), _, _, _, _) }
5641
}
5742

58-
final class Location = LocationImpl;
43+
class Location = LocationClass<LocationInput>::Location;
5944

6045
/** A program element with a location. */
6146
class Locatable extends @locatable {

go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ private import semmle.go.dataflow.FlowSummary
44
private import DataFlowPrivate
55
private import FlowSummaryImpl as FlowSummaryImpl
66
private import semmle.go.dataflow.ExternalFlow
7+
private import semmle.go.internal.Locations
78

89
cached
910
private newtype TNode =
@@ -158,12 +159,7 @@ module Public {
158159
}
159160

160161
/** Gets the location of this node. */
161-
Location getLocation() {
162-
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
163-
this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
164-
result.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
165-
)
166-
}
162+
Location getLocation() { result = getDataFlowNodeLocation(this) }
167163

168164
/** Gets the file in which this node appears. */
169165
File getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }

go/ql/lib/semmle/go/internal/Locations.qll

Lines changed: 81 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,76 @@
22

33
import go
44

5+
/** Provides the input to `LocationClass`. */
6+
signature module LocationClassInputSig {
7+
class Base;
8+
9+
predicate locationInfo(
10+
Base b, string filepath, int startline, int startcolumn, int endline, int endcolumn
11+
);
12+
13+
File getFile(Base b);
14+
}
15+
16+
/** Provides a class layer for locations. */
17+
module LocationClass<LocationClassInputSig Input> {
18+
private import Input
19+
20+
/**
21+
* A location as given by a file, a start line, a start column,
22+
* an end line, and an end column.
23+
*
24+
* For more information about locations see [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
25+
*/
26+
final class Location instanceof Base {
27+
/** Gets the file for this location. */
28+
File getFile() { result = getFile(this) }
29+
30+
/** Gets the 1-based line number (inclusive) where this location starts. */
31+
int getStartLine() { locationInfo(this, _, result, _, _, _) }
32+
33+
/** Gets the 1-based column number (inclusive) where this location starts. */
34+
int getStartColumn() { locationInfo(this, _, _, result, _, _) }
35+
36+
/** Gets the 1-based line number (inclusive) where this location ends. */
37+
int getEndLine() { locationInfo(this, _, _, _, result, _) }
38+
39+
/** Gets the 1-based column number (inclusive) where this location ends. */
40+
int getEndColumn() { locationInfo(this, _, _, _, _, result) }
41+
42+
/** Gets the number of lines covered by this location. */
43+
int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 }
44+
45+
/** Gets a textual representation of this element. */
46+
string toString() {
47+
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
48+
this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
49+
result = filepath + "@" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
50+
)
51+
}
52+
53+
/**
54+
* Holds if this element is at the specified location.
55+
* The location spans column `startcolumn` of line `startline` to
56+
* column `endcolumn` of line `endline` in file `filepath`.
57+
* For more information, see
58+
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
59+
*/
60+
predicate hasLocationInfo(
61+
string filepath, int startline, int startcolumn, int endline, int endcolumn
62+
) {
63+
locationInfo(this, filepath, startline, startcolumn, endline, endcolumn)
64+
}
65+
}
66+
}
67+
568
// Should _not_ be cached, as that would require the data flow stage to be evaluated
669
// in order to evaluate the AST stage. Ideally, we would cache each injector separately,
770
// but that's not possible. Instead, we cache all predicates that need the injectors
871
// to be tuple numbered.
972
newtype TLocation =
1073
TDbLocation(@location loc) or
11-
TSynthLocation(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
74+
TDataFlowNodeLocation(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
1275
any(DataFlow::Node n).hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
1376
// avoid overlap with existing DB locations
1477
not existingDBLocation(filepath, startline, startcolumn, endline, endcolumn)
@@ -24,91 +87,6 @@ private predicate existingDBLocation(
2487
)
2588
}
2689

27-
/**
28-
* A location as given by a file, a start line, a start column,
29-
* an end line, and an end column.
30-
*
31-
* For more information about locations see [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
32-
*/
33-
abstract class LocationImpl extends TLocation {
34-
/** Gets the file for this location. */
35-
abstract File getFile();
36-
37-
/** Gets the 1-based line number (inclusive) where this location starts. */
38-
abstract int getStartLine();
39-
40-
/** Gets the 1-based column number (inclusive) where this location starts. */
41-
abstract int getStartColumn();
42-
43-
/** Gets the 1-based line number (inclusive) where this location ends. */
44-
abstract int getEndLine();
45-
46-
/** Gets the 1-based column number (inclusive) where this location ends. */
47-
abstract int getEndColumn();
48-
49-
/** Gets the number of lines covered by this location. */
50-
int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 }
51-
52-
/** Gets a textual representation of this element. */
53-
string toString() {
54-
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
55-
this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
56-
result = filepath + "@" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
57-
)
58-
}
59-
60-
/**
61-
* Holds if this element is at the specified location.
62-
* The location spans column `startcolumn` of line `startline` to
63-
* column `endcolumn` of line `endline` in file `filepath`.
64-
* For more information, see
65-
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
66-
*/
67-
abstract predicate hasLocationInfo(
68-
string filepath, int startline, int startcolumn, int endline, int endcolumn
69-
);
70-
}
71-
72-
class DbLocationImpl extends LocationImpl instanceof DbLocation {
73-
private @location loc;
74-
75-
DbLocationImpl() { this = TDbLocation(loc) }
76-
77-
override File getFile() { result = DbLocation.super.getFile() }
78-
79-
override int getStartLine() { result = DbLocation.super.getStartLine() }
80-
81-
override int getStartColumn() { result = DbLocation.super.getStartColumn() }
82-
83-
override int getEndLine() { result = DbLocation.super.getEndLine() }
84-
85-
override int getEndColumn() { result = DbLocation.super.getEndColumn() }
86-
87-
override predicate hasLocationInfo(
88-
string filepath, int startline, int startcolumn, int endline, int endcolumn
89-
) {
90-
DbLocation.super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
91-
}
92-
}
93-
94-
class SynthLocationImpl extends LocationImpl, TSynthLocation {
95-
override File getFile() { synthLocationInfo(this, result.getAbsolutePath(), _, _, _, _) }
96-
97-
override int getStartLine() { synthLocationInfo(this, _, result, _, _, _) }
98-
99-
override int getStartColumn() { synthLocationInfo(this, _, _, result, _, _) }
100-
101-
override int getEndLine() { synthLocationInfo(this, _, _, _, result, _) }
102-
103-
override int getEndColumn() { synthLocationInfo(this, _, _, _, _, result) }
104-
105-
override predicate hasLocationInfo(
106-
string filepath, int startline, int startcolumn, int endline, int endcolumn
107-
) {
108-
synthLocationInfo(this, filepath, startline, startcolumn, endline, endcolumn)
109-
}
110-
}
111-
11290
cached
11391
private module Cached {
11492
cached
@@ -143,8 +121,21 @@ private module Cached {
143121
import Cached
144122

145123
cached
146-
private predicate synthLocationInfo(
147-
SynthLocationImpl l, string filepath, int startline, int startcolumn, int endline, int endcolumn
148-
) {
149-
l = TSynthLocation(filepath, startline, startcolumn, endline, endcolumn)
124+
private module DataFlowNodes {
125+
cached
126+
predicate dataFlowNodeLocationInfo(
127+
Location l, string filepath, int startline, int startcolumn, int endline, int endcolumn
128+
) {
129+
l = TDataFlowNodeLocation(filepath, startline, startcolumn, endline, endcolumn)
130+
}
131+
132+
cached
133+
Location getDataFlowNodeLocation(DataFlow::Node n) {
134+
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
135+
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
136+
result.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
137+
)
138+
}
150139
}
140+
141+
import DataFlowNodes

0 commit comments

Comments
 (0)