|
2 | 2 | overlay[local?]
|
3 | 3 | module;
|
4 | 4 |
|
| 5 | +private import Location |
| 6 | + |
5 | 7 | /** A type with `toString`. */
|
6 | 8 | private signature class TypeWithToString {
|
7 | 9 | bindingset[this]
|
8 | 10 | string toString();
|
9 | 11 | }
|
10 | 12 |
|
| 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 | + |
11 | 23 | /**
|
12 | 24 | * Constructs an `Option` type that is a disjoint union of the given type and an
|
13 | 25 | * additional singleton element.
|
@@ -45,3 +57,91 @@ module Option<TypeWithToString T> {
|
45 | 57 | /** Gets the given element wrapped as an `Option`. */
|
46 | 58 | Some some(T c) { result = TSome(c) }
|
47 | 59 | }
|
| 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