@@ -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' ;
@@ -682,19 +687,56 @@ export class CodeQLCliServer implements Disposable {
682687
683688 async interpretBqrs ( metadata : QueryMetadata , resultsPath : string , interpretedResultsPath : string , sourceInfo ?: SourceInfo ) : Promise < sarif . Log > {
684689 await this . runInterpretCommand ( SARIF_FORMAT , metadata , resultsPath , interpretedResultsPath , sourceInfo ) ;
685-
686- let output : string ;
687- try {
688- output = await fs . readFile ( interpretedResultsPath , 'utf8' ) ;
689- } catch ( e ) {
690- const rawMessage = e . stderr || e . message ;
691- const errorMessage = rawMessage . startsWith ( 'Cannot create a string' )
692- ? `SARIF too large. ${ rawMessage } `
693- : rawMessage ;
694- throw new Error ( `Reading output of interpretation failed: ${ errorMessage } ` ) ;
695- }
696690 try {
697- return JSON . parse ( output ) as sarif . Log ;
691+ // Parse the SARIF file into token streams, filtering out only the results array.
692+ const p = parser ( ) ;
693+ const pipeline = chain ( [
694+ fs . createReadStream ( interpretedResultsPath ) ,
695+ p ,
696+ pick ( { filter : 'runs.0.results' } ) ,
697+ verifier ( )
698+ ] ) ;
699+
700+ // Creates JavaScript objects from the token stream
701+ const asm = Assembler . connectTo ( pipeline ) ;
702+
703+ // Returns a constructed Log object with the results or an empty array if no results were found.
704+ // If the parser fails for any reason, it will reject the promise.
705+ return await new Promise ( ( resolve , reject ) => {
706+ pipeline . on ( 'error' , ( error ) => {
707+ reject ( error ) ;
708+ } ) ;
709+
710+ asm . on ( 'done' , ( asm ) => {
711+ const dummyTool : sarif . Tool = { driver : { name : '' } } ;
712+ if ( asm . current ) {
713+ const log : sarif . Log = {
714+ version : '2.1.0' ,
715+ runs : [
716+ {
717+ tool : dummyTool ,
718+ results : asm . current
719+ }
720+ ]
721+ } ;
722+
723+ resolve ( log ) ;
724+ } else {
725+ const log : sarif . Log = {
726+ version : '2.1.0' ,
727+ runs : [
728+ {
729+ tool : dummyTool ,
730+ results : [ ]
731+ }
732+ ]
733+ } ;
734+
735+ resolve ( log ) ;
736+ }
737+
738+ } ) ;
739+ } ) ;
698740 } catch ( err ) {
699741 throw new Error ( `Parsing output of interpretation failed: ${ err . stderr || err } ` ) ;
700742 }
0 commit comments