Merge branch 'main' into robertbrignull/extract_progress
This commit is contained in:
90
extensions/ql-vscode/src/ast-cfg-commands.ts
Normal file
90
extensions/ql-vscode/src/ast-cfg-commands.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import { Uri, window } from "vscode";
|
||||
import { withProgress } from "./commandRunner";
|
||||
import { AstViewer } from "./astViewer";
|
||||
import {
|
||||
TemplatePrintAstProvider,
|
||||
TemplatePrintCfgProvider,
|
||||
} from "./contextual/templateProvider";
|
||||
import { compileAndRunQuery } from "./local-queries";
|
||||
import { QueryRunner } from "./queryRunner";
|
||||
import { QueryHistoryManager } from "./query-history/query-history-manager";
|
||||
import { DatabaseUI } from "./local-databases-ui";
|
||||
import { ResultsView } from "./interface";
|
||||
import { AstCfgCommands } from "./common/commands";
|
||||
|
||||
type AstCfgOptions = {
|
||||
queryRunner: QueryRunner;
|
||||
queryHistoryManager: QueryHistoryManager;
|
||||
databaseUI: DatabaseUI;
|
||||
localQueryResultsView: ResultsView;
|
||||
queryStorageDir: string;
|
||||
|
||||
astViewer: AstViewer;
|
||||
astTemplateProvider: TemplatePrintAstProvider;
|
||||
cfgTemplateProvider: TemplatePrintCfgProvider;
|
||||
};
|
||||
|
||||
export function getAstCfgCommands({
|
||||
queryRunner,
|
||||
queryHistoryManager,
|
||||
databaseUI,
|
||||
localQueryResultsView,
|
||||
queryStorageDir,
|
||||
astViewer,
|
||||
astTemplateProvider,
|
||||
cfgTemplateProvider,
|
||||
}: AstCfgOptions): AstCfgCommands {
|
||||
const viewAst = async (selectedFile: Uri) =>
|
||||
withProgress(
|
||||
async (progress, token) => {
|
||||
const ast = await astTemplateProvider.provideAst(
|
||||
progress,
|
||||
token,
|
||||
selectedFile ?? window.activeTextEditor?.document.uri,
|
||||
);
|
||||
if (ast) {
|
||||
astViewer.updateRoots(await ast.getRoots(), ast.db, ast.fileName);
|
||||
}
|
||||
},
|
||||
{
|
||||
cancellable: true,
|
||||
title: "Calculate AST",
|
||||
},
|
||||
);
|
||||
|
||||
const viewCfg = async () =>
|
||||
withProgress(
|
||||
async (progress, token) => {
|
||||
const res = await cfgTemplateProvider.provideCfgUri(
|
||||
window.activeTextEditor?.document,
|
||||
);
|
||||
if (res) {
|
||||
await compileAndRunQuery(
|
||||
queryRunner,
|
||||
queryHistoryManager,
|
||||
databaseUI,
|
||||
localQueryResultsView,
|
||||
queryStorageDir,
|
||||
false,
|
||||
res[0],
|
||||
progress,
|
||||
token,
|
||||
undefined,
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Calculating Control Flow Graph",
|
||||
cancellable: true,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
"codeQL.viewAst": viewAst,
|
||||
"codeQL.viewAstContextExplorer": viewAst,
|
||||
"codeQL.viewAstContextEditor": viewAst,
|
||||
"codeQL.viewCfg": viewCfg,
|
||||
"codeQL.viewCfgContextExplorer": viewCfg,
|
||||
"codeQL.viewCfgContextEditor": viewCfg,
|
||||
};
|
||||
}
|
||||
@@ -23,11 +23,11 @@ import {
|
||||
isWholeFileLoc,
|
||||
isLineColumnLoc,
|
||||
} from "./pure/bqrs-utils";
|
||||
import { commandRunner } from "./commandRunner";
|
||||
import { DisposableObject } from "./pure/disposable-object";
|
||||
import { showAndLogExceptionWithTelemetry } from "./helpers";
|
||||
import { asError, getErrorMessage } from "./pure/helpers-pure";
|
||||
import { redactableError } from "./pure/errors";
|
||||
import { AstViewerCommands } from "./common/commands";
|
||||
|
||||
export interface AstItem {
|
||||
id: BqrsId;
|
||||
@@ -55,15 +55,6 @@ class AstViewerDataProvider
|
||||
readonly onDidChangeTreeData: Event<AstItem | undefined> =
|
||||
this._onDidChangeTreeData.event;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.push(
|
||||
commandRunner("codeQLAstViewer.gotoCode", async (item: AstItem) => {
|
||||
await showLocation(item.fileLocation);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
refresh(): void {
|
||||
this._onDidChangeTreeData.fire(undefined);
|
||||
}
|
||||
@@ -126,16 +117,20 @@ export class AstViewer extends DisposableObject {
|
||||
|
||||
this.push(this.treeView);
|
||||
this.push(this.treeDataProvider);
|
||||
this.push(
|
||||
commandRunner("codeQLAstViewer.clear", async () => {
|
||||
this.clear();
|
||||
}),
|
||||
);
|
||||
this.push(
|
||||
window.onDidChangeTextEditorSelection(this.updateTreeSelection, this),
|
||||
);
|
||||
}
|
||||
|
||||
getCommands(): AstViewerCommands {
|
||||
return {
|
||||
"codeQLAstViewer.clear": async () => this.clear(),
|
||||
"codeQLAstViewer.gotoCode": async (item: AstItem) => {
|
||||
await showLocation(item.fileLocation);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
updateRoots(roots: AstItem[], db: DatabaseItem, fileUri: Uri) {
|
||||
this.treeDataProvider.roots = roots;
|
||||
this.treeDataProvider.db = db;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { CommandManager } from "../packages/commands";
|
||||
import type { Uri, Range } from "vscode";
|
||||
import type { AstItem } from "../astViewer";
|
||||
import type { DbTreeViewItem } from "../databases/ui/db-tree-view-item";
|
||||
import type { DatabaseItem } from "../local-databases";
|
||||
import type { QueryHistoryInfo } from "../query-history/query-history-info";
|
||||
@@ -167,6 +168,20 @@ export type DatabasePanelCommands = {
|
||||
"codeQLVariantAnalysisRepositories.removeItemContextMenu": SingleSelectionCommandFunction<DbTreeViewItem>;
|
||||
};
|
||||
|
||||
export type AstCfgCommands = {
|
||||
"codeQL.viewAst": (selectedFile: Uri) => Promise<void>;
|
||||
"codeQL.viewAstContextExplorer": (selectedFile: Uri) => Promise<void>;
|
||||
"codeQL.viewAstContextEditor": (selectedFile: Uri) => Promise<void>;
|
||||
"codeQL.viewCfg": () => Promise<void>;
|
||||
"codeQL.viewCfgContextExplorer": () => Promise<void>;
|
||||
"codeQL.viewCfgContextEditor": () => Promise<void>;
|
||||
};
|
||||
|
||||
export type AstViewerCommands = {
|
||||
"codeQLAstViewer.clear": () => Promise<void>;
|
||||
"codeQLAstViewer.gotoCode": (item: AstItem) => Promise<void>;
|
||||
};
|
||||
|
||||
export type PackagingCommands = {
|
||||
"codeQL.installPackDependencies": () => Promise<void>;
|
||||
"codeQL.downloadPacks": () => Promise<void>;
|
||||
@@ -176,13 +191,20 @@ export type EvalLogViewerCommands = {
|
||||
"codeQLEvalLogViewer.clear": () => Promise<void>;
|
||||
};
|
||||
|
||||
export type SummaryLanguageSupportCommands = {
|
||||
"codeQL.gotoQL": () => Promise<void>;
|
||||
};
|
||||
|
||||
export type AllCommands = BaseCommands &
|
||||
QueryHistoryCommands &
|
||||
LocalDatabasesCommands &
|
||||
VariantAnalysisCommands &
|
||||
DatabasePanelCommands &
|
||||
AstCfgCommands &
|
||||
AstViewerCommands &
|
||||
PackagingCommands &
|
||||
EvalLogViewerCommands;
|
||||
EvalLogViewerCommands &
|
||||
SummaryLanguageSupportCommands;
|
||||
|
||||
export type AppCommandManager = CommandManager<AllCommands>;
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ import { QLTestAdapterFactory } from "./test-adapter";
|
||||
import { TestUIService } from "./test-ui";
|
||||
import { CompareView } from "./compare/compare-view";
|
||||
import { initializeTelemetry } from "./telemetry";
|
||||
import { commandRunner, commandRunnerWithProgress } from "./commandRunner";
|
||||
import { commandRunner } from "./commandRunner";
|
||||
import { ProgressCallback, withProgress } from "./progress";
|
||||
import { CodeQlStatusBarHandler } from "./status-bar";
|
||||
import { getPackagingCommands } from "./packaging";
|
||||
@@ -118,10 +118,10 @@ import {
|
||||
QueryServerCommands,
|
||||
} from "./common/commands";
|
||||
import {
|
||||
compileAndRunQuery,
|
||||
getLocalQueryCommands,
|
||||
showResultsForCompletedQuery,
|
||||
} from "./local-queries";
|
||||
import { getAstCfgCommands } from "./ast-cfg-commands";
|
||||
|
||||
/**
|
||||
* extension.ts
|
||||
@@ -664,6 +664,15 @@ async function activateWithInstalledDistribution(
|
||||
);
|
||||
const queryStorageDir = join(ctx.globalStorageUri.fsPath, "queries");
|
||||
await ensureDir(queryStorageDir);
|
||||
|
||||
// Store contextual queries in a temporary folder so that they are removed
|
||||
// when the application closes. There is no need for the user to interact with them.
|
||||
const contextualQueryStorageDir = join(
|
||||
tmpDir.name,
|
||||
"contextual-query-storage",
|
||||
);
|
||||
await ensureDir(contextualQueryStorageDir);
|
||||
|
||||
const labelProvider = new HistoryItemLabelProvider(
|
||||
queryHistoryConfigurationListener,
|
||||
);
|
||||
@@ -800,6 +809,20 @@ async function activateWithInstalledDistribution(
|
||||
ctx.subscriptions.push(testUIService);
|
||||
}
|
||||
|
||||
const astViewer = new AstViewer();
|
||||
const astTemplateProvider = new TemplatePrintAstProvider(
|
||||
cliServer,
|
||||
qs,
|
||||
dbm,
|
||||
contextualQueryStorageDir,
|
||||
);
|
||||
const cfgTemplateProvider = new TemplatePrintCfgProvider(cliServer, dbm);
|
||||
|
||||
ctx.subscriptions.push(astViewer);
|
||||
|
||||
const summaryLanguageSupport = new SummaryLanguageSupport();
|
||||
ctx.subscriptions.push(summaryLanguageSupport);
|
||||
|
||||
void extLogger.log("Registering top-level command palette commands.");
|
||||
|
||||
const allCommands: AllCommands = {
|
||||
@@ -808,10 +831,22 @@ async function activateWithInstalledDistribution(
|
||||
...variantAnalysisManager.getCommands(),
|
||||
...databaseUI.getCommands(),
|
||||
...dbModule.getCommands(),
|
||||
...getAstCfgCommands({
|
||||
queryRunner: qs,
|
||||
queryHistoryManager: qhm,
|
||||
databaseUI,
|
||||
localQueryResultsView,
|
||||
queryStorageDir,
|
||||
astViewer,
|
||||
astTemplateProvider,
|
||||
cfgTemplateProvider,
|
||||
}),
|
||||
...astViewer.getCommands(),
|
||||
...getPackagingCommands({
|
||||
cliServer,
|
||||
}),
|
||||
...evalLogViewer.getCommands(),
|
||||
...summaryLanguageSupport.getCommands(),
|
||||
};
|
||||
|
||||
for (const [commandName, command] of Object.entries(allCommands)) {
|
||||
@@ -908,8 +943,6 @@ async function activateWithInstalledDistribution(
|
||||
}),
|
||||
);
|
||||
|
||||
ctx.subscriptions.push(new SummaryLanguageSupport());
|
||||
|
||||
void extLogger.log("Starting language server.");
|
||||
await client.start();
|
||||
ctx.subscriptions.push({
|
||||
@@ -920,13 +953,6 @@ async function activateWithInstalledDistribution(
|
||||
// Jump-to-definition and find-references
|
||||
void extLogger.log("Registering jump-to-definition handlers.");
|
||||
|
||||
// Store contextual queries in a temporary folder so that they are removed
|
||||
// when the application closes. There is no need for the user to interact with them.
|
||||
const contextualQueryStorageDir = join(
|
||||
tmpDir.name,
|
||||
"contextual-query-storage",
|
||||
);
|
||||
await ensureDir(contextualQueryStorageDir);
|
||||
languages.registerDefinitionProvider(
|
||||
{ scheme: zipArchiveScheme },
|
||||
new TemplateQueryDefinitionProvider(
|
||||
@@ -947,174 +973,6 @@ async function activateWithInstalledDistribution(
|
||||
),
|
||||
);
|
||||
|
||||
const astViewer = new AstViewer();
|
||||
const printAstTemplateProvider = new TemplatePrintAstProvider(
|
||||
cliServer,
|
||||
qs,
|
||||
dbm,
|
||||
contextualQueryStorageDir,
|
||||
);
|
||||
const cfgTemplateProvider = new TemplatePrintCfgProvider(cliServer, dbm);
|
||||
|
||||
ctx.subscriptions.push(astViewer);
|
||||
|
||||
ctx.subscriptions.push(
|
||||
commandRunnerWithProgress(
|
||||
"codeQL.viewAst",
|
||||
async (
|
||||
progress: ProgressCallback,
|
||||
token: CancellationToken,
|
||||
selectedFile: Uri,
|
||||
) =>
|
||||
await viewAst(
|
||||
astViewer,
|
||||
printAstTemplateProvider,
|
||||
progress,
|
||||
token,
|
||||
selectedFile,
|
||||
),
|
||||
{
|
||||
cancellable: true,
|
||||
title: "Calculate AST",
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Since we are tracking extension usage through commands, this command mirrors the "codeQL.viewAst" command
|
||||
ctx.subscriptions.push(
|
||||
commandRunnerWithProgress(
|
||||
"codeQL.viewAstContextExplorer",
|
||||
async (
|
||||
progress: ProgressCallback,
|
||||
token: CancellationToken,
|
||||
selectedFile: Uri,
|
||||
) =>
|
||||
await viewAst(
|
||||
astViewer,
|
||||
printAstTemplateProvider,
|
||||
progress,
|
||||
token,
|
||||
selectedFile,
|
||||
),
|
||||
{
|
||||
cancellable: true,
|
||||
title: "Calculate AST",
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Since we are tracking extension usage through commands, this command mirrors the "codeQL.viewAst" command
|
||||
ctx.subscriptions.push(
|
||||
commandRunnerWithProgress(
|
||||
"codeQL.viewAstContextEditor",
|
||||
async (
|
||||
progress: ProgressCallback,
|
||||
token: CancellationToken,
|
||||
selectedFile: Uri,
|
||||
) =>
|
||||
await viewAst(
|
||||
astViewer,
|
||||
printAstTemplateProvider,
|
||||
progress,
|
||||
token,
|
||||
selectedFile,
|
||||
),
|
||||
{
|
||||
cancellable: true,
|
||||
title: "Calculate AST",
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
ctx.subscriptions.push(
|
||||
commandRunnerWithProgress(
|
||||
"codeQL.viewCfg",
|
||||
async (progress: ProgressCallback, token: CancellationToken) => {
|
||||
const res = await cfgTemplateProvider.provideCfgUri(
|
||||
window.activeTextEditor?.document,
|
||||
);
|
||||
if (res) {
|
||||
await compileAndRunQuery(
|
||||
qs,
|
||||
qhm,
|
||||
databaseUI,
|
||||
localQueryResultsView,
|
||||
queryStorageDir,
|
||||
false,
|
||||
res[0],
|
||||
progress,
|
||||
token,
|
||||
undefined,
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Calculating Control Flow Graph",
|
||||
cancellable: true,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Since we are tracking extension usage through commands, this command mirrors the "codeQL.viewCfg" command
|
||||
ctx.subscriptions.push(
|
||||
commandRunnerWithProgress(
|
||||
"codeQL.viewCfgContextExplorer",
|
||||
async (progress: ProgressCallback, token: CancellationToken) => {
|
||||
const res = await cfgTemplateProvider.provideCfgUri(
|
||||
window.activeTextEditor?.document,
|
||||
);
|
||||
if (res) {
|
||||
await compileAndRunQuery(
|
||||
qs,
|
||||
qhm,
|
||||
databaseUI,
|
||||
localQueryResultsView,
|
||||
queryStorageDir,
|
||||
false,
|
||||
res[0],
|
||||
progress,
|
||||
token,
|
||||
undefined,
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Calculating Control Flow Graph",
|
||||
cancellable: true,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Since we are tracking extension usage through commands, this command mirrors the "codeQL.viewCfg" command
|
||||
ctx.subscriptions.push(
|
||||
commandRunnerWithProgress(
|
||||
"codeQL.viewCfgContextEditor",
|
||||
async (progress: ProgressCallback, token: CancellationToken) => {
|
||||
const res = await cfgTemplateProvider.provideCfgUri(
|
||||
window.activeTextEditor?.document,
|
||||
);
|
||||
if (res) {
|
||||
await compileAndRunQuery(
|
||||
qs,
|
||||
qhm,
|
||||
databaseUI,
|
||||
localQueryResultsView,
|
||||
queryStorageDir,
|
||||
false,
|
||||
res[0],
|
||||
progress,
|
||||
token,
|
||||
undefined,
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Calculating Control Flow Graph",
|
||||
cancellable: true,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
const mockServer = new VSCodeMockGitHubApiServer(ctx);
|
||||
ctx.subscriptions.push(mockServer);
|
||||
ctx.subscriptions.push(
|
||||
@@ -1230,23 +1088,6 @@ async function openReferencedFile(
|
||||
}
|
||||
}
|
||||
|
||||
async function viewAst(
|
||||
astViewer: AstViewer,
|
||||
printAstTemplateProvider: TemplatePrintAstProvider,
|
||||
progress: ProgressCallback,
|
||||
token: CancellationToken,
|
||||
selectedFile: Uri,
|
||||
): Promise<void> {
|
||||
const ast = await printAstTemplateProvider.provideAst(
|
||||
progress,
|
||||
token,
|
||||
selectedFile ?? window.activeTextEditor?.document.uri,
|
||||
);
|
||||
if (ast) {
|
||||
astViewer.updateRoots(await ast.getRoots(), ast.db, ast.fileName);
|
||||
}
|
||||
}
|
||||
|
||||
function addUnhandledRejectionListener() {
|
||||
const handler = (error: unknown) => {
|
||||
// This listener will be triggered for errors from other extensions as
|
||||
|
||||
@@ -13,9 +13,9 @@ import {
|
||||
workspace,
|
||||
} from "vscode";
|
||||
import { DisposableObject } from "../pure/disposable-object";
|
||||
import { commandRunner } from "../commandRunner";
|
||||
import { extLogger } from "../common";
|
||||
import { getErrorMessage } from "../pure/helpers-pure";
|
||||
import { SummaryLanguageSupportCommands } from "../common/commands";
|
||||
|
||||
/** A `Position` within a specified file on disk. */
|
||||
interface PositionInFile {
|
||||
@@ -73,8 +73,12 @@ export class SummaryLanguageSupport extends DisposableObject {
|
||||
this.handleDidCloseTextDocument.bind(this),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
this.push(commandRunner("codeQL.gotoQL", this.handleGotoQL.bind(this)));
|
||||
public getCommands(): SummaryLanguageSupportCommands {
|
||||
return {
|
||||
"codeQL.gotoQL": this.handleGotoQL.bind(this),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user