@@ -51,6 +51,7 @@ import {
5151 GRAPH_TABLE_NAME ,
5252 NavigationDirection ,
5353 getDefaultResultSetName ,
54+ RAW_RESULTS_LIMIT ,
5455} from "../common/interface-types" ;
5556import { extLogger } from "../common/logging/vscode" ;
5657import type { Logger } from "../common/logging" ;
@@ -62,6 +63,8 @@ import type {
6263import { interpretResultsSarif , interpretGraphResults } from "../query-results" ;
6364import type { QueryEvaluationInfo } from "../run-queries-shared" ;
6465import {
66+ getLocationsFromSarifResult ,
67+ normalizeFileUri ,
6568 parseSarifLocation ,
6669 parseSarifPlainTextMessage ,
6770} from "../common/sarif-utils" ;
@@ -82,7 +85,7 @@ import { redactableError } from "../common/errors";
8285import type { ResultsViewCommands } from "../common/commands" ;
8386import type { App } from "../common/app" ;
8487import type { Disposable } from "../common/disposable-object" ;
85- import type { RawResultSet } from "../common/raw-result-types" ;
88+ import type { RawResultSet , Row } from "../common/raw-result-types" ;
8689import type { BqrsResultSetSchema } from "../common/bqrs-cli-types" ;
8790import { CachedOperation } from "../language-support/contextual/cached-operation" ;
8891
@@ -349,6 +352,7 @@ export class ResultsView extends AbstractWebview<
349352 await this . openFile ( msg . filePath ) ;
350353 break ;
351354 case "requestFileFilteredResults" :
355+ void this . loadFileFilteredResults ( msg . fileUri , msg . selectedTable ) ;
352356 break ;
353357 case "telemetry" :
354358 telemetryListener ?. sendUIInteraction ( msg . action ) ;
@@ -1125,6 +1129,83 @@ export class ResultsView extends AbstractWebview<
11251129 return undefined ;
11261130 }
11271131
1132+ /**
1133+ * Loads all results from the given table that reference the given file URI,
1134+ * and sends them to the webview. Called on demand when the webview requests
1135+ * pre-filtered results for a specific (file, table) pair.
1136+ */
1137+ private async loadFileFilteredResults (
1138+ fileUri : string ,
1139+ selectedTable : string ,
1140+ ) : Promise < void > {
1141+ const query = this . _displayedQuery ;
1142+ if ( ! query ) {
1143+ void this . postMessage ( {
1144+ t : "setFileFilteredResults" ,
1145+ results : { fileUri, selectedTable } ,
1146+ } ) ;
1147+ return ;
1148+ }
1149+
1150+ const normalizedFilterUri = normalizeFileUri ( fileUri ) ;
1151+
1152+ let rawRows : Row [ ] | undefined ;
1153+ let sarifResults : Result [ ] | undefined ;
1154+
1155+ // Load and filter raw BQRS results
1156+ try {
1157+ const resultSetSchemas = await this . getResultSetSchemas (
1158+ query . completedQuery ,
1159+ ) ;
1160+ const schema = resultSetSchemas . find ( ( s ) => s . name === selectedTable ) ;
1161+
1162+ if ( schema && schema . rows > 0 ) {
1163+ const resultsPath = query . completedQuery . getResultsPath ( selectedTable ) ;
1164+ const chunk = await this . cliServer . bqrsDecode (
1165+ resultsPath ,
1166+ schema . name ,
1167+ {
1168+ offset : schema . pagination ?. offsets [ 0 ] ,
1169+ pageSize : schema . rows ,
1170+ } ,
1171+ ) ;
1172+ const resultSet = bqrsToResultSet ( schema , chunk ) ;
1173+ rawRows = filterRowsByFileUri ( resultSet . rows , normalizedFilterUri ) ;
1174+ if ( rawRows . length > RAW_RESULTS_LIMIT ) {
1175+ rawRows = rawRows . slice ( 0 , RAW_RESULTS_LIMIT ) ;
1176+ }
1177+ }
1178+ } catch ( e ) {
1179+ void this . logger . log (
1180+ `Error loading file-filtered raw results: ${ getErrorMessage ( e ) } ` ,
1181+ ) ;
1182+ }
1183+
1184+ // Filter SARIF results (already in memory)
1185+ if ( this . _interpretation ?. data . t === "SarifInterpretationData" ) {
1186+ const allResults = this . _interpretation . data . runs [ 0 ] ?. results ?? [ ] ;
1187+ sarifResults = allResults . filter ( ( result ) => {
1188+ const locations = getLocationsFromSarifResult (
1189+ result ,
1190+ this . _interpretation ! . sourceLocationPrefix ,
1191+ ) ;
1192+ return locations . some (
1193+ ( loc ) => normalizeFileUri ( loc . uri ) === normalizedFilterUri ,
1194+ ) ;
1195+ } ) ;
1196+ }
1197+
1198+ void this . postMessage ( {
1199+ t : "setFileFilteredResults" ,
1200+ results : {
1201+ fileUri,
1202+ selectedTable,
1203+ rawRows,
1204+ sarifResults,
1205+ } ,
1206+ } ) ;
1207+ }
1208+
11281209 dispose ( ) {
11291210 super . dispose ( ) ;
11301211
@@ -1133,3 +1214,32 @@ export class ResultsView extends AbstractWebview<
11331214 this . disposableEventListeners = [ ] ;
11341215 }
11351216}
1217+
1218+ /**
1219+ * Filters raw result rows to those that have at least one location
1220+ * referencing the given file (compared by normalized URI).
1221+ */
1222+ function filterRowsByFileUri ( rows : Row [ ] , normalizedFileUri : string ) : Row [ ] {
1223+ return rows . filter ( ( row ) => {
1224+ for ( const cell of row ) {
1225+ if ( cell . type !== "entity" ) {
1226+ continue ;
1227+ }
1228+ const url = cell . value . url ;
1229+ if ( ! url ) {
1230+ continue ;
1231+ }
1232+ let uri : string | undefined ;
1233+ if (
1234+ url . type === "wholeFileLocation" ||
1235+ url . type === "lineColumnLocation"
1236+ ) {
1237+ uri = url . uri ;
1238+ }
1239+ if ( uri !== undefined && normalizeFileUri ( uri ) === normalizedFileUri ) {
1240+ return true ;
1241+ }
1242+ }
1243+ return false ;
1244+ } ) ;
1245+ }
0 commit comments