Skip to content

Commit 42e8b32

Browse files
Merge pull request #20280 from joefarebrother/shared-loc-option
Shared: Add Option types with location
2 parents 0d0eaa2 + 1b808fe commit 42e8b32

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
* category: minorAnalysis
3+
---
4+
* Added `LocatableOption` and `OptionWithLocationInfo` as modules providing option types with location information.

shared/util/codeql/util/Option.qll

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,24 @@
22
overlay[local?]
33
module;
44

5+
private import Location
6+
57
/** A type with `toString`. */
68
private signature class TypeWithToString {
79
bindingset[this]
810
string toString();
911
}
1012

13+
/** A type with `toString` and `hasLocationInfo` */
14+
private signature class TypeWithLocationInfo {
15+
bindingset[this]
16+
string toString();
17+
18+
predicate hasLocationInfo(
19+
string filePath, int startLine, int startColumn, int endLine, int endColumn
20+
);
21+
}
22+
1123
/**
1224
* Constructs an `Option` type that is a disjoint union of the given type and an
1325
* additional singleton element.
@@ -45,3 +57,91 @@ module Option<TypeWithToString T> {
4557
/** Gets the given element wrapped as an `Option`. */
4658
Some some(T c) { result = TSome(c) }
4759
}
60+
61+
/**
62+
* Constructs an `Option` type that is a disjoint union of the given type and an
63+
* additional singleton element, and has a `hasLocationInfo` predicate.
64+
* `T` must have a `hasLocationInfo` predicate.
65+
*/
66+
module OptionWithLocationInfo<TypeWithLocationInfo T> {
67+
private module O = Option<T>;
68+
69+
final private class BaseOption = O::Option;
70+
71+
/**
72+
* An option type. This is either a singleton `None` or a `Some` wrapping the
73+
* given type.
74+
*/
75+
class Option extends BaseOption {
76+
/**
77+
* Holds if this element is at the specified location.
78+
* The location spans column `startColumn` of line `startLine` to
79+
* column `endColumn` of line `endLine` in file `filepath`.
80+
* For more information, see
81+
* [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
82+
*/
83+
predicate hasLocationInfo(
84+
string filePath, int startLine, int startColumn, int endLine, int endColumn
85+
) {
86+
this.isNone() and
87+
filePath = "" and
88+
startLine = 0 and
89+
startColumn = 0 and
90+
endLine = 0 and
91+
endColumn = 0
92+
or
93+
this.asSome().hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn)
94+
}
95+
}
96+
97+
/** The singleton `None` element. */
98+
class None extends Option instanceof O::None { }
99+
100+
/** A wrapper for the given type. */
101+
class Some extends Option instanceof O::Some { }
102+
103+
/** Gets the given element wrapped as an `Option`. */
104+
Some some(T c) { result.asSome() = c }
105+
}
106+
107+
private module WithLocation<LocationSig Location> {
108+
signature class LocatableType {
109+
bindingset[this]
110+
string toString();
111+
112+
Location getLocation();
113+
}
114+
}
115+
116+
/**
117+
* Constructs an `Option` type that is a disjoint union of the given type and an
118+
* additional singleton element, and has a `getLocation` predicate.
119+
* `T` must have a `getLocation` predicate with a result type of `Location`.
120+
*/
121+
module LocatableOption<LocationSig Location, WithLocation<Location>::LocatableType T> {
122+
private module O = Option<T>;
123+
124+
final private class BaseOption = O::Option;
125+
126+
/**
127+
* An option type. This is either a singleton `None` or a `Some` wrapping the
128+
* given type.
129+
*/
130+
class Option extends BaseOption {
131+
Location getLocation() {
132+
result = this.asSome().getLocation()
133+
or
134+
this.isNone() and
135+
result.hasLocationInfo("", 0, 0, 0, 0)
136+
}
137+
}
138+
139+
/** The singleton `None` element. */
140+
class None extends Option instanceof O::None { }
141+
142+
/** A wrapper for the given type. */
143+
class Some extends Option instanceof O::Some { }
144+
145+
/** Gets the given element wrapped as an `Option`. */
146+
Some some(T c) { result.asSome() = c }
147+
}

0 commit comments

Comments
 (0)