@@ -6,7 +6,6 @@ import { dirname, join, delimiter } from "path";
66import * as sarif from "sarif" ;
77import { SemVer } from "semver" ;
88import { Readable } from "stream" ;
9- import { StringDecoder } from "string_decoder" ;
109import tk from "tree-kill" ;
1110import { promisify } from "util" ;
1211import { CancellationToken , Disposable , Uri } from "vscode" ;
@@ -31,6 +30,7 @@ import { CompilationMessage } from "../query-server/legacy-messages";
3130import { sarifParser } from "../common/sarif-parser" ;
3231import { App } from "../common/app" ;
3332import { QueryLanguage } from "../common/query-language" ;
33+ import { LINE_ENDINGS , splitStreamAtSeparators } from "../common/split-stream" ;
3434
3535/**
3636 * The version of the SARIF format that we are using.
@@ -1649,120 +1649,13 @@ export async function runCodeQlCliCommand(
16491649 }
16501650}
16511651
1652- /**
1653- * Buffer to hold state used when splitting a text stream into lines.
1654- */
1655- class SplitBuffer {
1656- private readonly decoder = new StringDecoder ( "utf8" ) ;
1657- private readonly maxSeparatorLength : number ;
1658- private buffer = "" ;
1659- private searchIndex = 0 ;
1660-
1661- constructor ( private readonly separators : readonly string [ ] ) {
1662- this . maxSeparatorLength = separators
1663- . map ( ( s ) => s . length )
1664- . reduce ( ( a , b ) => Math . max ( a , b ) , 0 ) ;
1665- }
1666-
1667- /**
1668- * Append new text data to the buffer.
1669- * @param chunk The chunk of data to append.
1670- */
1671- public addChunk ( chunk : Buffer ) : void {
1672- this . buffer += this . decoder . write ( chunk ) ;
1673- }
1674-
1675- /**
1676- * Signal that the end of the input stream has been reached.
1677- */
1678- public end ( ) : void {
1679- this . buffer += this . decoder . end ( ) ;
1680- this . buffer += this . separators [ 0 ] ; // Append a separator to the end to ensure the last line is returned.
1681- }
1682-
1683- /**
1684- * A version of startsWith that isn't overriden by a broken version of ms-python.
1685- *
1686- * The definition comes from
1687- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
1688- * which is CC0/public domain
1689- *
1690- * See https://github.com/github/vscode-codeql/issues/802 for more context as to why we need it.
1691- */
1692- private static startsWith (
1693- s : string ,
1694- searchString : string ,
1695- position : number ,
1696- ) : boolean {
1697- const pos = position > 0 ? position | 0 : 0 ;
1698- return s . substring ( pos , pos + searchString . length ) === searchString ;
1699- }
1700-
1701- /**
1702- * Extract the next full line from the buffer, if one is available.
1703- * @returns The text of the next available full line (without the separator), or `undefined` if no
1704- * line is available.
1705- */
1706- public getNextLine ( ) : string | undefined {
1707- while ( this . searchIndex <= this . buffer . length - this . maxSeparatorLength ) {
1708- for ( const separator of this . separators ) {
1709- if ( SplitBuffer . startsWith ( this . buffer , separator , this . searchIndex ) ) {
1710- const line = this . buffer . slice ( 0 , this . searchIndex ) ;
1711- this . buffer = this . buffer . slice ( this . searchIndex + separator . length ) ;
1712- this . searchIndex = 0 ;
1713- return line ;
1714- }
1715- }
1716- this . searchIndex ++ ;
1717- }
1718-
1719- return undefined ;
1720- }
1721- }
1722-
1723- /**
1724- * Splits a text stream into lines based on a list of valid line separators.
1725- * @param stream The text stream to split. This stream will be fully consumed.
1726- * @param separators The list of strings that act as line separators.
1727- * @returns A sequence of lines (not including separators).
1728- */
1729- async function * splitStreamAtSeparators (
1730- stream : Readable ,
1731- separators : string [ ] ,
1732- ) : AsyncGenerator < string , void , unknown > {
1733- const buffer = new SplitBuffer ( separators ) ;
1734- for await ( const chunk of stream ) {
1735- buffer . addChunk ( chunk ) ;
1736- let line : string | undefined ;
1737- do {
1738- line = buffer . getNextLine ( ) ;
1739- if ( line !== undefined ) {
1740- yield line ;
1741- }
1742- } while ( line !== undefined ) ;
1743- }
1744- buffer . end ( ) ;
1745- let line : string | undefined ;
1746- do {
1747- line = buffer . getNextLine ( ) ;
1748- if ( line !== undefined ) {
1749- yield line ;
1750- }
1751- } while ( line !== undefined ) ;
1752- }
1753-
1754- /**
1755- * Standard line endings for splitting human-readable text.
1756- */
1757- const lineEndings = [ "\r\n" , "\r" , "\n" ] ;
1758-
17591652/**
17601653 * Log a text stream to a `Logger` interface.
17611654 * @param stream The stream to log.
17621655 * @param logger The logger that will consume the stream output.
17631656 */
17641657async function logStream ( stream : Readable , logger : BaseLogger ) : Promise < void > {
1765- for await ( const line of splitStreamAtSeparators ( stream , lineEndings ) ) {
1658+ for await ( const line of splitStreamAtSeparators ( stream , LINE_ENDINGS ) ) {
17661659 // Await the result of log here in order to ensure the logs are written in the correct order.
17671660 await logger . log ( line ) ;
17681661 }
0 commit comments