Shared: Add approximate version of getASelected{Source,Sink}Location

This commit is contained in:
Asger F
2025-07-01 14:54:41 +02:00
parent d1b4172486
commit 8b345518f4
4 changed files with 82 additions and 2 deletions

View File

@@ -459,6 +459,15 @@ module Configs<LocationSig Location, InputSig<Location> Lang> {
*/
default Location getASelectedSourceLocation(Node source) { result = source.getLocation() }
/**
* Like `getASelectedSourceLocation`, but only has to get a location _containing_ the
* actual location associated with `source`.
*
* This prunes fewer sources than `getASelectedSourceLocation` but leaves room for the possibility
* that a more precise location can be selected in the query.
*/
default Location getASelectedSourceLocationApprox(Node source) { none() }
/**
* Gets a location that will be associated with the given `sink` in a
* diff-informed query that uses this configuration (see
@@ -469,6 +478,15 @@ module Configs<LocationSig Location, InputSig<Location> Lang> {
* report the sink at all, this predicate can be `none()`.
*/
default Location getASelectedSinkLocation(Node sink) { result = sink.getLocation() }
/**
* Like `getASelectedSinkLocation`, but only has to get a location _containing_ the
* actual location associated with `sink`.
*
* This prunes fewer sinks than `getASelectedSinkLocation` but leaves room for the possibility
* that a more precise location can be selected in the query.
*/
default Location getASelectedSinkLocationApprox(Node sink) { none() }
}
/** An input configuration for data flow using flow state. */
@@ -608,6 +626,15 @@ module Configs<LocationSig Location, InputSig<Location> Lang> {
*/
default Location getASelectedSourceLocation(Node source) { result = source.getLocation() }
/**
* Like `getASelectedSourceLocation`, but only has to get a location _containing_ the
* actual location associated with `source`.
*
* This prunes fewer sources than `getASelectedSourceLocation` but leaves room for the possibility
* that a more precise location can be selected in the query.
*/
default Location getASelectedSourceLocationApprox(Node source) { none() }
/**
* Gets a location that will be associated with the given `sink` in a
* diff-informed query that uses this configuration (see
@@ -618,6 +645,15 @@ module Configs<LocationSig Location, InputSig<Location> Lang> {
* report the sink at all, this predicate can be `none()`.
*/
default Location getASelectedSinkLocation(Node sink) { result = sink.getLocation() }
/**
* Like `getASelectedSinkLocation`, but only has to get a location _containing_ the
* actual location associated with `sink`.
*
* This prunes fewer sinks than `getASelectedSinkLocation` but leaves room for the possibility
* that a more precise location can be selected in the query.
*/
default Location getASelectedSinkLocationApprox(Node sink) { none() }
}
}

View File

@@ -145,7 +145,11 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
Location getASelectedSourceLocation(Node source);
Location getASelectedSourceLocationApprox(Node source);
Location getASelectedSinkLocation(Node sink);
Location getASelectedSinkLocationApprox(Node sink);
}
/**

View File

@@ -133,7 +133,9 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
private predicate isFilteredSource(Node source) {
Config::isSource(source, _) and
if Config::observeDiffInformedIncrementalMode()
then AlertFiltering::filterByLocation(Config::getASelectedSourceLocation(source))
then
AlertFiltering::filterByLocation(Config::getASelectedSourceLocation(source)) or
AlertFiltering::filterByLocationApprox(Config::getASelectedSourceLocationApprox(source))
else any()
}
@@ -144,7 +146,9 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
Config::isSink(sink)
) and
if Config::observeDiffInformedIncrementalMode()
then AlertFiltering::filterByLocation(Config::getASelectedSinkLocation(sink))
then
AlertFiltering::filterByLocation(Config::getASelectedSinkLocation(sink)) or
AlertFiltering::filterByLocationApprox(Config::getASelectedSinkLocationApprox(sink))
else any()
}

View File

@@ -107,4 +107,40 @@ module AlertFilteringImpl<LocationSig Location> {
location.hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn)
)
}
/**
* Holds if some subrange within `location` would be accepted by alert filtering.
*
* There does not need to exist a `Location` corresponding to that subrange.
*/
bindingset[location]
predicate filterByLocationApprox(Location location) {
not restrictAlertsTo(_, _, _) and not restrictAlertsToExactLocation(_, _, _, _, _)
or
exists(string filePath |
restrictAlertsToEntireFile(filePath) and
location.hasLocationInfo(filePath, _, _, _, _)
or
exists(int locStartLine, int locEndLine |
location.hasLocationInfo(filePath, locStartLine, _, locEndLine, _)
|
restrictAlertsToStartLine(filePath, [locStartLine .. locEndLine])
)
)
or
// Check if an exact filter-location is fully contained in `location`.
// This is slow but only used for testing.
exists(
string filePath, int startLine, int startColumn, int endLine, int endColumn,
int filterStartLine, int filterStartColumn, int filterEndLine, int filterEndColumn
|
location.hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn) and
restrictAlertsToExactLocation(filePath, filterStartLine, filterStartColumn, filterEndLine,
filterEndColumn) and
startLine <= filterStartLine and
(startLine != filterStartLine or startColumn <= filterStartColumn) and
endLine >= filterEndLine and
(endLine != filterEndLine or endColumn >= filterEndColumn)
)
}
}