@@ -2,6 +2,11 @@ import * as cpp from 'child-process-promise';
22import * as child_process from 'child_process' ;
33import * as fs from 'fs-extra' ;
44import * as path from 'path' ;
5+ import { parser } from 'stream-json' ;
6+ import { pick } from 'stream-json/filters/Pick' ;
7+ import { verifier } from 'stream-json/utils/Verifier' ;
8+ import Assembler = require( 'stream-json/Assembler' ) ;
9+ import { chain } from 'stream-chain' ;
510import * as sarif from 'sarif' ;
611import { SemVer } from 'semver' ;
712import { Readable } from 'stream' ;
@@ -669,19 +674,56 @@ export class CodeQLCliServer implements Disposable {
669674
670675 async interpretBqrs ( metadata : QueryMetadata , resultsPath : string , interpretedResultsPath : string , sourceInfo ?: SourceInfo ) : Promise < sarif . Log > {
671676 await this . runInterpretCommand ( SARIF_FORMAT , metadata , resultsPath , interpretedResultsPath , sourceInfo ) ;
672-
673- let output : string ;
674- try {
675- output = await fs . readFile ( interpretedResultsPath , 'utf8' ) ;
676- } catch ( e ) {
677- const rawMessage = e . stderr || e . message ;
678- const errorMessage = rawMessage . startsWith ( 'Cannot create a string' )
679- ? `SARIF too large. ${ rawMessage } `
680- : rawMessage ;
681- throw new Error ( `Reading output of interpretation failed: ${ errorMessage } ` ) ;
682- }
683677 try {
684- return JSON . parse ( output ) as sarif . Log ;
678+ // Parse the SARIF file into token streams, filtering out only the results array.
679+ const p = parser ( ) ;
680+ const pipeline = chain ( [
681+ fs . createReadStream ( interpretedResultsPath ) ,
682+ p ,
683+ pick ( { filter : 'runs.0.results' } ) ,
684+ verifier ( )
685+ ] ) ;
686+
687+ // Creates JavaScript objects from the token stream
688+ const asm = Assembler . connectTo ( pipeline ) ;
689+
690+ // Returns a constructed Log object with the results or an empty array if no results were found.
691+ // If the parser fails for any reason, it will reject the promise.
692+ return await new Promise ( ( resolve , reject ) => {
693+ pipeline . on ( 'error' , ( error ) => {
694+ reject ( error ) ;
695+ } ) ;
696+
697+ asm . on ( 'done' , ( asm ) => {
698+ const dummyTool : sarif . Tool = { driver : { name : '' } } ;
699+ if ( asm . current ) {
700+ const log : sarif . Log = {
701+ version : '2.1.0' ,
702+ runs : [
703+ {
704+ tool : dummyTool ,
705+ results : asm . current
706+ }
707+ ]
708+ } ;
709+
710+ resolve ( log ) ;
711+ } else {
712+ const log : sarif . Log = {
713+ version : '2.1.0' ,
714+ runs : [
715+ {
716+ tool : dummyTool ,
717+ results : [ ]
718+ }
719+ ]
720+ } ;
721+
722+ resolve ( log ) ;
723+ }
724+
725+ } ) ;
726+ } ) ;
685727 } catch ( err ) {
686728 throw new Error ( `Parsing output of interpretation failed: ${ err . stderr || err } ` ) ;
687729 }
0 commit comments