mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #20280 from joefarebrother/shared-loc-option
Shared: Add Option types with location
This commit is contained in:
4
shared/util/change-notes/2025-08-25-loc-option.md
Normal file
4
shared/util/change-notes/2025-08-25-loc-option.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
* category: minorAnalysis
|
||||
---
|
||||
* Added `LocatableOption` and `OptionWithLocationInfo` as modules providing option types with location information.
|
||||
@@ -2,12 +2,24 @@
|
||||
overlay[local?]
|
||||
module;
|
||||
|
||||
private import Location
|
||||
|
||||
/** A type with `toString`. */
|
||||
private signature class TypeWithToString {
|
||||
bindingset[this]
|
||||
string toString();
|
||||
}
|
||||
|
||||
/** A type with `toString` and `hasLocationInfo` */
|
||||
private signature class TypeWithLocationInfo {
|
||||
bindingset[this]
|
||||
string toString();
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filePath, int startLine, int startColumn, int endLine, int endColumn
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an `Option` type that is a disjoint union of the given type and an
|
||||
* additional singleton element.
|
||||
@@ -45,3 +57,91 @@ module Option<TypeWithToString T> {
|
||||
/** Gets the given element wrapped as an `Option`. */
|
||||
Some some(T c) { result = TSome(c) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an `Option` type that is a disjoint union of the given type and an
|
||||
* additional singleton element, and has a `hasLocationInfo` predicate.
|
||||
* `T` must have a `hasLocationInfo` predicate.
|
||||
*/
|
||||
module OptionWithLocationInfo<TypeWithLocationInfo T> {
|
||||
private module O = Option<T>;
|
||||
|
||||
final private class BaseOption = O::Option;
|
||||
|
||||
/**
|
||||
* An option type. This is either a singleton `None` or a `Some` wrapping the
|
||||
* given type.
|
||||
*/
|
||||
class Option extends BaseOption {
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startColumn` of line `startLine` to
|
||||
* column `endColumn` of line `endLine` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filePath, int startLine, int startColumn, int endLine, int endColumn
|
||||
) {
|
||||
this.isNone() and
|
||||
filePath = "" and
|
||||
startLine = 0 and
|
||||
startColumn = 0 and
|
||||
endLine = 0 and
|
||||
endColumn = 0
|
||||
or
|
||||
this.asSome().hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn)
|
||||
}
|
||||
}
|
||||
|
||||
/** The singleton `None` element. */
|
||||
class None extends Option instanceof O::None { }
|
||||
|
||||
/** A wrapper for the given type. */
|
||||
class Some extends Option instanceof O::Some { }
|
||||
|
||||
/** Gets the given element wrapped as an `Option`. */
|
||||
Some some(T c) { result.asSome() = c }
|
||||
}
|
||||
|
||||
private module WithLocation<LocationSig Location> {
|
||||
signature class LocatableType {
|
||||
bindingset[this]
|
||||
string toString();
|
||||
|
||||
Location getLocation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an `Option` type that is a disjoint union of the given type and an
|
||||
* additional singleton element, and has a `getLocation` predicate.
|
||||
* `T` must have a `getLocation` predicate with a result type of `Location`.
|
||||
*/
|
||||
module LocatableOption<LocationSig Location, WithLocation<Location>::LocatableType T> {
|
||||
private module O = Option<T>;
|
||||
|
||||
final private class BaseOption = O::Option;
|
||||
|
||||
/**
|
||||
* An option type. This is either a singleton `None` or a `Some` wrapping the
|
||||
* given type.
|
||||
*/
|
||||
class Option extends BaseOption {
|
||||
Location getLocation() {
|
||||
result = this.asSome().getLocation()
|
||||
or
|
||||
this.isNone() and
|
||||
result.hasLocationInfo("", 0, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
/** The singleton `None` element. */
|
||||
class None extends Option instanceof O::None { }
|
||||
|
||||
/** A wrapper for the given type. */
|
||||
class Some extends Option instanceof O::Some { }
|
||||
|
||||
/** Gets the given element wrapped as an `Option`. */
|
||||
Some some(T c) { result.asSome() = c }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user