From 69a8dc429049955fb7ef81806dd0df17c97a66fb Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 18 Feb 2026 13:31:03 +0100 Subject: [PATCH 1/2] Add 'View DFG' command, similar to 'View CFG' --- extensions/ql-vscode/package.json | 33 ++++++++ extensions/ql-vscode/src/common/commands.ts | 3 + extensions/ql-vscode/src/extension.ts | 17 +++- .../ast-viewer/ast-cfg-commands.ts | 79 ++++++++++++------- .../language-support/contextual/key-type.ts | 6 ++ .../contextual/template-provider.ts | 24 +++--- 6 files changed, 119 insertions(+), 43 deletions(-) diff --git a/extensions/ql-vscode/package.json b/extensions/ql-vscode/package.json index 9b5440ff0d7..55c0d724335 100644 --- a/extensions/ql-vscode/package.json +++ b/extensions/ql-vscode/package.json @@ -807,6 +807,18 @@ "command": "codeQL.viewCfgContextEditor", "title": "CodeQL: View CFG" }, + { + "command": "codeQL.viewDfg", + "title": "CodeQL: View DFG" + }, + { + "command": "codeQL.viewDfgContextExplorer", + "title": "CodeQL: View DFG" + }, + { + "command": "codeQL.viewDfgContextEditor", + "title": "CodeQL: View DFG" + }, { "command": "codeQL.upgradeCurrentDatabase", "title": "CodeQL: Upgrade Current Database" @@ -1402,6 +1414,11 @@ "group": "9_qlCommands", "when": "resourceScheme == codeql-zip-archive && config.codeQL.canary" }, + { + "command": "codeQL.viewDfgContextExplorer", + "group": "9_qlCommands", + "when": "resourceScheme == codeql-zip-archive && config.codeQL.canary" + }, { "command": "codeQL.runQueries", "group": "9_qlCommands", @@ -1615,6 +1632,18 @@ "command": "codeQL.viewCfgContextEditor", "when": "false" }, + { + "command": "codeQL.viewDfg", + "when": "resourceScheme == codeql-zip-archive && config.codeQL.canary" + }, + { + "command": "codeQL.viewDfgContextExplorer", + "when": "false" + }, + { + "command": "codeQL.viewDfgContextEditor", + "when": "false" + }, { "command": "codeQL.openModelEditor" }, @@ -1907,6 +1936,10 @@ "command": "codeQL.viewCfgContextEditor", "when": "resourceScheme == codeql-zip-archive && config.codeQL.canary" }, + { + "command": "codeQL.viewDfgContextEditor", + "when": "resourceScheme == codeql-zip-archive && config.codeQL.canary" + }, { "command": "codeQL.quickEvalContextEditor", "when": "editorLangId == ql && debugState == inactive" diff --git a/extensions/ql-vscode/src/common/commands.ts b/extensions/ql-vscode/src/common/commands.ts index f4126194aa2..38ddcf2517f 100644 --- a/extensions/ql-vscode/src/common/commands.ts +++ b/extensions/ql-vscode/src/common/commands.ts @@ -318,6 +318,9 @@ export type AstCfgCommands = { "codeQL.viewCfg": () => Promise; "codeQL.viewCfgContextExplorer": () => Promise; "codeQL.viewCfgContextEditor": () => Promise; + "codeQL.viewDfg": () => Promise; + "codeQL.viewDfgContextExplorer": () => Promise; + "codeQL.viewDfgContextEditor": () => Promise; }; export type AstViewerCommands = { diff --git a/extensions/ql-vscode/src/extension.ts b/extensions/ql-vscode/src/extension.ts index cda8a62e0f9..308aa6c4df9 100644 --- a/extensions/ql-vscode/src/extension.ts +++ b/extensions/ql-vscode/src/extension.ts @@ -40,8 +40,9 @@ import { createLanguageClient, getQueryEditorCommands, install, + KeyType, TemplatePrintAstProvider, - TemplatePrintCfgProvider, + TemplatePrintGraphProvider, TemplateQueryDefinitionProvider, TemplateQueryReferenceProvider, } from "./language-support"; @@ -1075,7 +1076,18 @@ async function activateWithInstalledDistribution( dbm, contextualQueryStorageDir, ); - const cfgTemplateProvider = new TemplatePrintCfgProvider(cliServer, dbm); + const cfgTemplateProvider = new TemplatePrintGraphProvider( + cliServer, + dbm, + KeyType.PrintCfgQuery, + "CFG", + ); + const dfgTemplateProvider = new TemplatePrintGraphProvider( + cliServer, + dbm, + KeyType.PrintDfgQuery, + "DFG", + ); ctx.subscriptions.push(astViewer); @@ -1111,6 +1123,7 @@ async function activateWithInstalledDistribution( astViewer, astTemplateProvider, cfgTemplateProvider, + dfgTemplateProvider, }), ...astViewer.getCommands(), ...getPackagingCommands({ diff --git a/extensions/ql-vscode/src/language-support/ast-viewer/ast-cfg-commands.ts b/extensions/ql-vscode/src/language-support/ast-viewer/ast-cfg-commands.ts index c6cf025832d..a9866cebac0 100644 --- a/extensions/ql-vscode/src/language-support/ast-viewer/ast-cfg-commands.ts +++ b/extensions/ql-vscode/src/language-support/ast-viewer/ast-cfg-commands.ts @@ -7,14 +7,15 @@ import type { LocalQueries } from "../../local-queries"; import { QuickEvalType } from "../../local-queries"; import type { TemplatePrintAstProvider, - TemplatePrintCfgProvider, + TemplatePrintGraphProvider, } from "../contextual/template-provider"; type AstCfgOptions = { localQueries: LocalQueries; astViewer: AstViewer; astTemplateProvider: TemplatePrintAstProvider; - cfgTemplateProvider: TemplatePrintCfgProvider; + cfgTemplateProvider: TemplatePrintGraphProvider; + dfgTemplateProvider: TemplatePrintGraphProvider; }; export function getAstCfgCommands({ @@ -22,6 +23,7 @@ export function getAstCfgCommands({ astViewer, astTemplateProvider, cfgTemplateProvider, + dfgTemplateProvider, }: AstCfgOptions): AstCfgCommands { const viewAst = async (selectedFile: Uri) => withProgress( @@ -41,35 +43,49 @@ export function getAstCfgCommands({ }, ); - const viewCfg = async () => - withProgress( - async (progress, token) => { - const editor = window.activeTextEditor; - const res = !editor - ? undefined - : await cfgTemplateProvider.provideCfgUri( - editor.document, - editor.selection.active.line + 1, - editor.selection.active.character + 1, + const viewGraph = ( + provider: TemplatePrintGraphProvider, + title: string, + ) => { + return async () => + withProgress( + async (progress, token) => { + const editor = window.activeTextEditor; + const res = !editor + ? undefined + : await provider.provideGraphUri( + editor.document, + editor.selection.active.line + 1, + editor.selection.active.character + 1, + ); + if (res) { + await localQueries.compileAndRunQuery( + QuickEvalType.None, + res[0], + progress, + token, + undefined, + false, + undefined, + res[1], ); - if (res) { - await localQueries.compileAndRunQuery( - QuickEvalType.None, - res[0], - progress, - token, - undefined, - false, - undefined, - res[1], - ); - } - }, - { - title: "Calculating Control Flow Graph", - cancellable: true, - }, - ); + } + }, + { + title, + cancellable: true, + }, + ); + }; + + const viewCfg = viewGraph( + cfgTemplateProvider, + "Calculating Control Flow Graph", + ); + const viewDfg = viewGraph( + dfgTemplateProvider, + "Calculating Data Flow Graph", + ); return { "codeQL.viewAst": viewAst, @@ -78,5 +94,8 @@ export function getAstCfgCommands({ "codeQL.viewCfg": viewCfg, "codeQL.viewCfgContextExplorer": viewCfg, "codeQL.viewCfgContextEditor": viewCfg, + "codeQL.viewDfg": viewDfg, + "codeQL.viewDfgContextExplorer": viewDfg, + "codeQL.viewDfgContextEditor": viewDfg, }; } diff --git a/extensions/ql-vscode/src/language-support/contextual/key-type.ts b/extensions/ql-vscode/src/language-support/contextual/key-type.ts index 244537ccaba..a1572947287 100644 --- a/extensions/ql-vscode/src/language-support/contextual/key-type.ts +++ b/extensions/ql-vscode/src/language-support/contextual/key-type.ts @@ -3,6 +3,7 @@ export enum KeyType { ReferenceQuery = "ReferenceQuery", PrintAstQuery = "PrintAstQuery", PrintCfgQuery = "PrintCfgQuery", + PrintDfgQuery = "PrintDfgQuery", } export function tagOfKeyType(keyType: KeyType): string { @@ -15,6 +16,8 @@ export function tagOfKeyType(keyType: KeyType): string { return "ide-contextual-queries/print-ast"; case KeyType.PrintCfgQuery: return "ide-contextual-queries/print-cfg"; + case KeyType.PrintDfgQuery: + return "ide-contextual-queries/print-dfg"; } } @@ -28,6 +31,8 @@ export function nameOfKeyType(keyType: KeyType): string { return "print AST"; case KeyType.PrintCfgQuery: return "print CFG"; + case KeyType.PrintDfgQuery: + return "print DFG"; } } @@ -38,6 +43,7 @@ export function kindOfKeyType(keyType: KeyType): string { return "definitions"; case KeyType.PrintAstQuery: case KeyType.PrintCfgQuery: + case KeyType.PrintDfgQuery: return "graph"; } } diff --git a/extensions/ql-vscode/src/language-support/contextual/template-provider.ts b/extensions/ql-vscode/src/language-support/contextual/template-provider.ts index 8d9cf6327ec..ecf9ec41cf9 100644 --- a/extensions/ql-vscode/src/language-support/contextual/template-provider.ts +++ b/extensions/ql-vscode/src/language-support/contextual/template-provider.ts @@ -282,10 +282,10 @@ export class TemplatePrintAstProvider { } /** - * Run templated CodeQL queries to produce CFG information for - * source-language files. + * Run templated CodeQL queries to produce graph information (e.g. CFG or DFG) + * for source-language files. */ -export class TemplatePrintCfgProvider { +export class TemplatePrintGraphProvider { private cache: CachedOperation< [number, number], [Uri, Record] @@ -294,11 +294,13 @@ export class TemplatePrintCfgProvider { constructor( private cli: CodeQLCliServer, private dbm: DatabaseManager, + private keyType: KeyType, + private displayName: string, ) { - this.cache = new CachedOperation(this.getCfgUri.bind(this)); + this.cache = new CachedOperation(this.getGraphUri.bind(this)); } - async provideCfgUri( + async provideGraphUri( document: TextDocument, line: number, character: number, @@ -309,14 +311,14 @@ export class TemplatePrintCfgProvider { line, character, ) - : await this.getCfgUri(document.uri.toString(), line, character); + : await this.getGraphUri(document.uri.toString(), line, character); } private shouldUseCache() { return !(isCanary() && NO_CACHE_AST_VIEWER.getValue()); } - private async getCfgUri( + private async getGraphUri( uriString: string, line: number, character: number, @@ -324,7 +326,7 @@ export class TemplatePrintCfgProvider { const uri = Uri.parse(uriString, true); if (uri.scheme !== zipArchiveScheme) { throw new Error( - "CFG Viewing is only available for databases with zipped source archives.", + `${this.displayName} Viewing is only available for databases with zipped source archives.`, ); } @@ -345,16 +347,16 @@ export class TemplatePrintCfgProvider { const queries = await resolveContextualQueries( this.cli, qlpack, - KeyType.PrintCfgQuery, + this.keyType, ); if (queries.length > 1) { throw new Error( - `Found multiple Print CFG queries. Can't continue. Make sure there is exacly one query with the tag ${KeyType.PrintCfgQuery}`, + `Found multiple Print ${this.displayName} queries. Can't continue. Make sure there is exacly one query with the tag ${this.keyType}`, ); } if (queries.length === 0) { throw new Error( - `Did not find any Print CFG queries. Can't continue. Make sure there is exacly one query with the tag ${KeyType.PrintCfgQuery}`, + `Did not find any Print ${this.displayName} queries. Can't continue. Make sure there is exacly one query with the tag ${this.keyType}`, ); } From 0b34d19a7fd3d02338ea5fd27fd503175d5f66a2 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 20 Feb 2026 11:25:39 +0100 Subject: [PATCH 2/2] Fix formatting and error messages in graph provider - Collapse viewGraph parameters and calls to single lines per formatter - Use tagOfKeyType() instead of raw enum value in error messages - Fix 'exacly' typo to 'exactly' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../language-support/ast-viewer/ast-cfg-commands.ts | 10 ++-------- .../language-support/contextual/template-provider.ts | 6 +++--- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/extensions/ql-vscode/src/language-support/ast-viewer/ast-cfg-commands.ts b/extensions/ql-vscode/src/language-support/ast-viewer/ast-cfg-commands.ts index a9866cebac0..f38f05719d9 100644 --- a/extensions/ql-vscode/src/language-support/ast-viewer/ast-cfg-commands.ts +++ b/extensions/ql-vscode/src/language-support/ast-viewer/ast-cfg-commands.ts @@ -43,10 +43,7 @@ export function getAstCfgCommands({ }, ); - const viewGraph = ( - provider: TemplatePrintGraphProvider, - title: string, - ) => { + const viewGraph = (provider: TemplatePrintGraphProvider, title: string) => { return async () => withProgress( async (progress, token) => { @@ -82,10 +79,7 @@ export function getAstCfgCommands({ cfgTemplateProvider, "Calculating Control Flow Graph", ); - const viewDfg = viewGraph( - dfgTemplateProvider, - "Calculating Data Flow Graph", - ); + const viewDfg = viewGraph(dfgTemplateProvider, "Calculating Data Flow Graph"); return { "codeQL.viewAst": viewAst, diff --git a/extensions/ql-vscode/src/language-support/contextual/template-provider.ts b/extensions/ql-vscode/src/language-support/contextual/template-provider.ts index ecf9ec41cf9..7f3a0968846 100644 --- a/extensions/ql-vscode/src/language-support/contextual/template-provider.ts +++ b/extensions/ql-vscode/src/language-support/contextual/template-provider.ts @@ -20,7 +20,7 @@ import type { DatabaseManager } from "../../databases/local-databases"; import { CachedOperation } from "./cached-operation"; import type { ProgressCallback } from "../../common/vscode/progress"; import { withProgress } from "../../common/vscode/progress"; -import { KeyType } from "./key-type"; +import { KeyType, tagOfKeyType } from "./key-type"; import type { FullLocationLink } from "./location-finder"; import { getLocationsForUriString, @@ -351,12 +351,12 @@ export class TemplatePrintGraphProvider { ); if (queries.length > 1) { throw new Error( - `Found multiple Print ${this.displayName} queries. Can't continue. Make sure there is exacly one query with the tag ${this.keyType}`, + `Found multiple Print ${this.displayName} queries. Can't continue. Make sure there is exactly one query with the tag ${tagOfKeyType(this.keyType)}`, ); } if (queries.length === 0) { throw new Error( - `Did not find any Print ${this.displayName} queries. Can't continue. Make sure there is exacly one query with the tag ${this.keyType}`, + `Did not find any Print ${this.displayName} queries. Can't continue. Make sure there is exactly one query with the tag ${tagOfKeyType(this.keyType)}`, ); }