diff --git a/extensions/ql-vscode/src/cli.ts b/extensions/ql-vscode/src/cli.ts index a0283b28e11..14f826a50a6 100644 --- a/extensions/ql-vscode/src/cli.ts +++ b/extensions/ql-vscode/src/cli.ts @@ -683,7 +683,7 @@ export class CodeQLCliServer implements Disposable { const subcommandArgs = [ '--format=text', `--end-summary=${endSummaryPath}`, - '--sourcemap', + ...(await this.cliConstraints.supportsSourceMap() ? ['--sourcemap'] : []), inputPath, outputPath ]; @@ -1322,6 +1322,11 @@ export class CliVersionConstraint { */ public static CLI_VERSION_WITH_PER_QUERY_EVAL_LOG = new SemVer('2.9.0'); + /** + * CLI version that supports the `--sourcemap` option for log generation. + */ + public static CLI_VERSION_WITH_SOURCEMAP = new SemVer('2.10.3'); + constructor(private readonly cli: CodeQLCliServer) { /**/ } @@ -1389,4 +1394,8 @@ export class CliVersionConstraint { async supportsPerQueryEvalLog() { return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_PER_QUERY_EVAL_LOG); } + + async supportsSourceMap() { + return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_SOURCEMAP); + } } diff --git a/extensions/ql-vscode/src/run-queries.ts b/extensions/ql-vscode/src/run-queries.ts index 916989acbdc..a60bf2af15a 100644 --- a/extensions/ql-vscode/src/run-queries.ts +++ b/extensions/ql-vscode/src/run-queries.ts @@ -36,7 +36,7 @@ import { compileDatabaseUpgradeSequence, hasNondestructiveUpgradeCapabilities, u import { ensureMetadataIsComplete } from './query-results'; import { SELECT_QUERY_NAME } from './contextual/locationFinder'; import { DecodedBqrsChunk } from './pure/bqrs-cli-types'; -import { getErrorMessage } from './pure/helpers-pure'; +import { asError, getErrorMessage } from './pure/helpers-pure'; import { generateSummarySymbolsFile } from './log-insights/summary-parser'; /** @@ -207,7 +207,10 @@ export class QueryEvaluationInfo { logPath: this.evalLogPath, }); if (await this.hasEvalLog()) { - this.displayHumanReadableLogSummary(queryInfo, qs); + queryInfo.evalLogLocation = this.evalLogPath; + queryInfo.evalLogSummaryLocation = await this.generateHumanReadableLogSummary(qs); + void this.logEndSummary(queryInfo.evalLogSummaryLocation, qs); // Logged asynchrnously + if (config.isCanary()) { // Generate JSON summary for viewer. await qs.cliServer.generateJsonLogSummary(this.evalLogPath, this.jsonEvalLogSummaryPath); queryInfo.jsonEvalLogSummaryLocation = this.jsonEvalLogSummaryPath; @@ -340,25 +343,40 @@ export class QueryEvaluationInfo { } /** - * Calls the appropriate CLI command to generate a human-readable log summary - * and logs to the Query Server console and query log file. + * Calls the appropriate CLI command to generate a human-readable log summary. + * @param qs The query server client. + * @returns The path to the log summary, or `undefined` if the summary could not be generated. */ - displayHumanReadableLogSummary(queryInfo: LocalQueryInfo, qs: qsClient.QueryServerClient): void { - queryInfo.evalLogLocation = this.evalLogPath; - void qs.cliServer.generateLogSummary(this.evalLogPath, this.evalLogSummaryPath, this.evalLogEndSummaryPath) - .then(() => { - queryInfo.evalLogSummaryLocation = this.evalLogSummaryPath; - fs.readFile(this.evalLogEndSummaryPath, (err, buffer) => { - if (err) { - throw new Error(`Could not read structured evaluator log end of summary file at ${this.evalLogEndSummaryPath}.`); - } - void qs.logger.log(' --- Evaluator Log Summary --- ', { additionalLogLocation: this.logPath }); - void qs.logger.log(buffer.toString(), { additionalLogLocation: this.logPath }); - }); - }) - .catch(err => { - void showAndLogWarningMessage(`Failed to generate human-readable structured evaluator log summary. Reason: ${err.message}`); - }); + private async generateHumanReadableLogSummary(qs: qsClient.QueryServerClient): Promise { + try { + await qs.cliServer.generateLogSummary(this.evalLogPath, this.evalLogSummaryPath, this.evalLogEndSummaryPath); + return this.evalLogSummaryPath; + + } catch (e) { + const err = asError(e); + void showAndLogWarningMessage(`Failed to generate human-readable structured evaluator log summary. Reason: ${err.message}`); + return undefined; + } + } + + /** + * Logs the end summary to the Output window and log file. + * @param logSummaryPath Path to the human-readable log summary + * @param qs The query server client. + */ + private async logEndSummary(logSummaryPath: string | undefined, qs: qsClient.QueryServerClient): Promise { + if (logSummaryPath === undefined) { + // Failed to generate the log, so we don't expect an end summary either. + return; + } + + try { + const endSummaryContent = await fs.readFile(this.evalLogEndSummaryPath, 'utf-8'); + void qs.logger.log(' --- Evaluator Log Summary --- ', { additionalLogLocation: this.logPath }); + void qs.logger.log(endSummaryContent, { additionalLogLocation: this.logPath }); + } catch (e) { + void showAndLogWarningMessage(`Could not read structured evaluator log end of summary file at ${this.evalLogEndSummaryPath}.`); + } } /**