diff --git a/extensions/ql-vscode/src/extension.ts b/extensions/ql-vscode/src/extension.ts index b6522377f..212abe0ac 100644 --- a/extensions/ql-vscode/src/extension.ts +++ b/extensions/ql-vscode/src/extension.ts @@ -109,10 +109,7 @@ import { handleInstallPackDependencies, } from "./packaging"; import { HistoryItemLabelProvider } from "./query-history/history-item-label-provider"; -import { - exportSelectedVariantAnalysisResults, - exportVariantAnalysisResults, -} from "./variant-analysis/export-results"; +import { exportSelectedVariantAnalysisResults } from "./variant-analysis/export-results"; import { EvalLogViewer } from "./eval-log-viewer"; import { SummaryLanguageSupport } from "./log-insights/summary-language-support"; import { JoinOrderScannerProvider } from "./log-insights/join-order"; @@ -1156,35 +1153,10 @@ async function activateWithInstalledDistribution( ctx.subscriptions.push( commandRunner("codeQL.exportSelectedVariantAnalysisResults", async () => { - await exportSelectedVariantAnalysisResults(qhm); + await exportSelectedVariantAnalysisResults(variantAnalysisManager, qhm); }), ); - ctx.subscriptions.push( - commandRunnerWithProgress( - "codeQL.exportVariantAnalysisResults", - async ( - progress: ProgressCallback, - token: CancellationToken, - variantAnalysisId: number, - filterSort?: RepositoriesFilterSortStateWithIds, - ) => { - await exportVariantAnalysisResults( - variantAnalysisManager, - variantAnalysisId, - filterSort, - app.credentials, - progress, - token, - ); - }, - { - title: "Exporting variant analysis results", - cancellable: true, - }, - ), - ); - ctx.subscriptions.push( commandRunner( "codeQL.loadVariantAnalysisRepoResults", diff --git a/extensions/ql-vscode/src/query-history/query-history-manager.ts b/extensions/ql-vscode/src/query-history/query-history-manager.ts index 44529bdf1..3b31c4e52 100644 --- a/extensions/ql-vscode/src/query-history/query-history-manager.ts +++ b/extensions/ql-vscode/src/query-history/query-history-manager.ts @@ -1238,8 +1238,7 @@ export class QueryHistoryManager extends DisposableObject { return; } - await commands.executeCommand( - "codeQL.exportVariantAnalysisResults", + await this.variantAnalysisManager.exportResults( finalSingleItem.variantAnalysis.id, ); } diff --git a/extensions/ql-vscode/src/variant-analysis/export-results.ts b/extensions/ql-vscode/src/variant-analysis/export-results.ts index faf3f0ee5..7b5647a00 100644 --- a/extensions/ql-vscode/src/variant-analysis/export-results.ts +++ b/extensions/ql-vscode/src/variant-analysis/export-results.ts @@ -9,7 +9,11 @@ import { window, workspace, } from "vscode"; -import { ProgressCallback, UserCancellationException } from "../commandRunner"; +import { + ProgressCallback, + UserCancellationException, + withProgress, +} from "../commandRunner"; import { showInformationMessageWithAction } from "../helpers"; import { extLogger } from "../common"; import { QueryHistoryManager } from "../query-history/query-history-manager"; @@ -37,6 +41,7 @@ import { Credentials } from "../common/authentication"; * Exports the results of the currently-selected variant analysis. */ export async function exportSelectedVariantAnalysisResults( + variantAnalysisManager: VariantAnalysisManager, queryHistoryManager: QueryHistoryManager, ): Promise { const queryHistoryItem = queryHistoryManager.getCurrentQueryHistoryItem(); @@ -46,8 +51,7 @@ export async function exportSelectedVariantAnalysisResults( ); } - return commands.executeCommand( - "codeQL.exportVariantAnalysisResults", + await variantAnalysisManager.exportResults( queryHistoryItem.variantAnalysis.id, ); } @@ -63,108 +67,117 @@ export async function exportVariantAnalysisResults( variantAnalysisId: number, filterSort: RepositoriesFilterSortStateWithIds | undefined, credentials: Credentials, - progress: ProgressCallback, - token: CancellationToken, ): Promise { - const variantAnalysis = await variantAnalysisManager.getVariantAnalysis( - variantAnalysisId, - ); - if (!variantAnalysis) { - void extLogger.log( - `Could not find variant analysis with id ${variantAnalysisId}`, - ); - throw new Error( - "There was an error when trying to retrieve variant analysis information", - ); - } + await withProgress( + async (progress: ProgressCallback, token: CancellationToken) => { + const variantAnalysis = await variantAnalysisManager.getVariantAnalysis( + variantAnalysisId, + ); + if (!variantAnalysis) { + void extLogger.log( + `Could not find variant analysis with id ${variantAnalysisId}`, + ); + throw new Error( + "There was an error when trying to retrieve variant analysis information", + ); + } - if (token.isCancellationRequested) { - throw new UserCancellationException("Cancelled"); - } + if (token.isCancellationRequested) { + throw new UserCancellationException("Cancelled"); + } - const repoStates = await variantAnalysisManager.getRepoStates( - variantAnalysisId, - ); - - void extLogger.log( - `Exporting variant analysis results for variant analysis with id ${variantAnalysis.id}`, - ); - - progress({ - maxStep: MAX_VARIANT_ANALYSIS_EXPORT_PROGRESS_STEPS, - step: 0, - message: "Determining export format", - }); - - const exportFormat = await determineExportFormat(); - if (!exportFormat) { - return; - } - - if (token.isCancellationRequested) { - throw new UserCancellationException("Cancelled"); - } - - const repositories = filterAndSortRepositoriesWithResults( - variantAnalysis.scannedRepos, - filterSort, - )?.filter( - (repo) => - repo.resultCount && - repoStates.find((r) => r.repositoryId === repo.repository.id) - ?.downloadStatus === - VariantAnalysisScannedRepositoryDownloadStatus.Succeeded, - ); - - async function* getAnalysesResults(): AsyncGenerator< - [VariantAnalysisScannedRepository, VariantAnalysisScannedRepositoryResult] - > { - if (!variantAnalysis) { - return; - } - - if (!repositories) { - return; - } - - for (const repo of repositories) { - const result = await variantAnalysisManager.loadResults( - variantAnalysis.id, - repo.repository.fullName, - { - skipCacheStore: true, - }, + const repoStates = await variantAnalysisManager.getRepoStates( + variantAnalysisId, ); - yield [repo, result]; - } - } + void extLogger.log( + `Exporting variant analysis results for variant analysis with id ${variantAnalysis.id}`, + ); - const exportDirectory = - variantAnalysisManager.getVariantAnalysisStorageLocation( - variantAnalysis.id, - ); + progress({ + maxStep: MAX_VARIANT_ANALYSIS_EXPORT_PROGRESS_STEPS, + step: 0, + message: "Determining export format", + }); - // The date will be formatted like the following: 20221115T123456Z. The time is in UTC. - const formattedDate = new Date() - .toISOString() - .replace(/[-:]/g, "") - .replace(/\.\d+Z$/, "Z"); - const exportedResultsDirectory = join( - exportDirectory, - "exported-results", - `results_${formattedDate}`, - ); + const exportFormat = await determineExportFormat(); + if (!exportFormat) { + return; + } - await exportVariantAnalysisAnalysisResults( - exportedResultsDirectory, - variantAnalysis, - getAnalysesResults(), - repositories?.length ?? 0, - exportFormat, - credentials, - progress, - token, + if (token.isCancellationRequested) { + throw new UserCancellationException("Cancelled"); + } + + const repositories = filterAndSortRepositoriesWithResults( + variantAnalysis.scannedRepos, + filterSort, + )?.filter( + (repo) => + repo.resultCount && + repoStates.find((r) => r.repositoryId === repo.repository.id) + ?.downloadStatus === + VariantAnalysisScannedRepositoryDownloadStatus.Succeeded, + ); + + async function* getAnalysesResults(): AsyncGenerator< + [ + VariantAnalysisScannedRepository, + VariantAnalysisScannedRepositoryResult, + ] + > { + if (!variantAnalysis) { + return; + } + + if (!repositories) { + return; + } + + for (const repo of repositories) { + const result = await variantAnalysisManager.loadResults( + variantAnalysis.id, + repo.repository.fullName, + { + skipCacheStore: true, + }, + ); + + yield [repo, result]; + } + } + + const exportDirectory = + variantAnalysisManager.getVariantAnalysisStorageLocation( + variantAnalysis.id, + ); + + // The date will be formatted like the following: 20221115T123456Z. The time is in UTC. + const formattedDate = new Date() + .toISOString() + .replace(/[-:]/g, "") + .replace(/\.\d+Z$/, "Z"); + const exportedResultsDirectory = join( + exportDirectory, + "exported-results", + `results_${formattedDate}`, + ); + + await exportVariantAnalysisAnalysisResults( + exportedResultsDirectory, + variantAnalysis, + getAnalysesResults(), + repositories?.length ?? 0, + exportFormat, + credentials, + progress, + token, + ); + }, + { + title: "Exporting variant analysis results", + cancellable: true, + }, ); } diff --git a/extensions/ql-vscode/src/variant-analysis/variant-analysis-manager.ts b/extensions/ql-vscode/src/variant-analysis/variant-analysis-manager.ts index 23f43c567..9bd7f201d 100644 --- a/extensions/ql-vscode/src/variant-analysis/variant-analysis-manager.ts +++ b/extensions/ql-vscode/src/variant-analysis/variant-analysis-manager.ts @@ -67,6 +67,7 @@ import { DbManager } from "../databases/db-manager"; import { App } from "../common/app"; import { redactableError } from "../pure/errors"; import { AppCommandManager, VariantAnalysisCommands } from "../common/commands"; +import { exportVariantAnalysisResults } from "./export-results"; export class VariantAnalysisManager extends DisposableObject @@ -690,6 +691,18 @@ export class VariantAnalysisManager await env.clipboard.writeText(text.join(EOL)); } + public async exportResults( + variantAnalysisId: number, + filterSort?: RepositoriesFilterSortStateWithIds, + ) { + await exportVariantAnalysisResults( + this, + variantAnalysisId, + filterSort, + this.app.credentials, + ); + } + private getRepoStatesStoragePath(variantAnalysisId: number): string { return join( this.getVariantAnalysisStorageLocation(variantAnalysisId), diff --git a/extensions/ql-vscode/src/variant-analysis/variant-analysis-view-manager.ts b/extensions/ql-vscode/src/variant-analysis/variant-analysis-view-manager.ts index 1fa1fe46d..88a7c46e2 100644 --- a/extensions/ql-vscode/src/variant-analysis/variant-analysis-view-manager.ts +++ b/extensions/ql-vscode/src/variant-analysis/variant-analysis-view-manager.ts @@ -3,6 +3,7 @@ import { VariantAnalysisScannedRepositoryState, } from "./shared/variant-analysis"; import { AppCommandManager } from "../common/commands"; +import { RepositoriesFilterSortStateWithIds } from "../pure/variant-analysis-filter-sort"; export interface VariantAnalysisViewInterface { variantAnalysisId: number; @@ -25,4 +26,8 @@ export interface VariantAnalysisViewManager< variantAnalysisId: number, ): Promise; openQueryFile(variantAnalysisId: number): Promise; + exportResults( + variantAnalysisId: number, + filterSort?: RepositoriesFilterSortStateWithIds, + ): Promise; } diff --git a/extensions/ql-vscode/src/variant-analysis/variant-analysis-view.ts b/extensions/ql-vscode/src/variant-analysis/variant-analysis-view.ts index 351e5afbf..e21830709 100644 --- a/extensions/ql-vscode/src/variant-analysis/variant-analysis-view.ts +++ b/extensions/ql-vscode/src/variant-analysis/variant-analysis-view.ts @@ -139,8 +139,7 @@ export class VariantAnalysisView ); break; case "exportResults": - void commands.executeCommand( - "codeQL.exportVariantAnalysisResults", + await this.manager.exportResults( this.variantAnalysisId, msg.filterSort, );