@@ -144,19 +144,58 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
144144 exists ( node )
145145 }
146146
147+ /**
148+ * Holds if `node` comes from a file that was in the diff for which we
149+ * are producing results.
150+ */
151+ overlay [ global]
152+ private predicate isDiffFileNode ( Node node ) {
153+ exists ( string filePath |
154+ node .getLocation ( ) .hasLocationInfo ( filePath , _, _, _, _) and
155+ AlertFiltering:: fileIsInDiff ( filePath )
156+ )
157+ }
158+
147159 overlay [ global]
148160 pragma [ nomagic]
149161 private predicate isFilteredSource ( Node source ) {
150162 Config:: isSource ( source , _) and
151- if Config:: observeDiffInformedIncrementalMode ( )
152- then AlertFiltering:: filterByLocation ( Config:: getASelectedSourceLocation ( source ) )
163+ // Data flow is always incremental in one of two ways.
164+ // 1. If the configuration is diff-informed and diff information is
165+ // available, we filter to only include nodes in the diff, which
166+ // gives the smallest set of nodes.
167+ // 2. If not, in global evaluation with overlay, we filter to only
168+ // include nodes from files in the overlay or the diff; flow from
169+ // other nodes will be added back later. There can be two reasons
170+ // why we are in this case:
171+ // 1. This could be the primary configuration for a query that
172+ // hasn't yet become diff-informed. In that case, the
173+ // `getASelectedSourceLocation` information is probably just the
174+ // default, and it's a fairly safe overapproximation to
175+ // effectively expand to all nodes in the file (via
176+ // `isDiffFileNode`).
177+ // 2. This could be a secondary configuration, like a helper
178+ // configuration for finding sources or sinks of a primary
179+ // configuration. In that case, the results of this configuration
180+ // are typically in the same file as the final alert.
181+ if
182+ Config:: observeDiffInformedIncrementalMode ( ) and
183+ AlertFiltering:: diffInformationAvailable ( )
184+ then AlertFiltering:: locationIsInDiff ( Config:: getASelectedSourceLocation ( source ) )
153185 else (
154186 // If we are in base-only global evaluation, do not filter out any sources.
155187 not isEvaluatingInOverlay ( )
156188 or
157189 // If we are in global evaluation with an overlay present, restrict
158- // sources to those visible in the overlay.
190+ // sources to those visible in the overlay or
159191 isOverlayNode ( source )
192+ or
193+ // those from files in the diff. The diff is a subset of the overlay
194+ // in the common case, but this is not guaranteed. Including the diff here
195+ // ensures that we re-evaluate flow that passes from a file in the
196+ // diff (but in the base), through a file in the overlay with
197+ // possibly important changes, back to the base.
198+ isDiffFileNode ( source )
160199 )
161200 }
162201
@@ -167,15 +206,17 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
167206 Config:: isSink ( sink , _) or
168207 Config:: isSink ( sink )
169208 ) and
170- if Config:: observeDiffInformedIncrementalMode ( )
171- then AlertFiltering:: filterByLocation ( Config:: getASelectedSinkLocation ( sink ) )
209+ // See the comments in `isFilteredSource` for the reasoning behind the following.
210+ if
211+ Config:: observeDiffInformedIncrementalMode ( ) and
212+ AlertFiltering:: diffInformationAvailable ( )
213+ then AlertFiltering:: locationIsInDiff ( Config:: getASelectedSinkLocation ( sink ) )
172214 else (
173- // If we are in base-only global evaluation, do not filter out any sinks.
174215 not isEvaluatingInOverlay ( )
175216 or
176- // If we are in global evaluation with an overlay present, restrict
177- // sinks to those visible in the overlay.
178217 isOverlayNode ( sink )
218+ or
219+ isDiffFileNode ( sink )
179220 )
180221 }
181222
0 commit comments