From 2d46e22b37885a05b23fdbfe629aefb7de265f01 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 13 May 2026 14:34:35 +0100 Subject: [PATCH] Add go/print-cfg --- go/ql/lib/printCfg.ql | 53 +++++++++++++++++++ .../go/controlflow/ControlFlowGraph.qll | 2 + .../go/controlflow/ControlFlowGraphShared.qll | 4 +- 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 go/ql/lib/printCfg.ql diff --git a/go/ql/lib/printCfg.ql b/go/ql/lib/printCfg.ql new file mode 100644 index 00000000000..f61d918ce98 --- /dev/null +++ b/go/ql/lib/printCfg.ql @@ -0,0 +1,53 @@ +/** + * @name Print CFG + * @description Produces a representation of a file's Control Flow Graph. + * This query is used by the VS Code extension. + * @id go/print-cfg + * @kind graph + * @tags ide-contextual-queries/print-cfg + */ + +import go +import semmle.go.controlflow.ControlFlowGraph +private import semmle.go.controlflow.ControlFlowGraphShared + +external string selectedSourceFile(); + +private predicate selectedSourceFileAlias = selectedSourceFile/0; + +external int selectedSourceLine(); + +private predicate selectedSourceLineAlias = selectedSourceLine/0; + +external int selectedSourceColumn(); + +private predicate selectedSourceColumnAlias = selectedSourceColumn/0; + +module ViewCfgQueryInput implements GoCfg::ControlFlow::ViewCfgQueryInputSig { + predicate selectedSourceFile = selectedSourceFileAlias/0; + + predicate selectedSourceLine = selectedSourceLineAlias/0; + + predicate selectedSourceColumn = selectedSourceColumnAlias/0; + + predicate cfgScopeSpan( + CfgScope scope, File file, int startLine, int startColumn, int endLine, int endColumn + ) { + file = scope.getFile() and + scope.getLocation().getStartLine() = startLine and + scope.getLocation().getStartColumn() = startColumn and + exists(Location loc | + loc.getEndLine() = endLine and + loc.getEndColumn() = endColumn and + loc = scope.(FuncDef).getBody().getLocation() + ) + or + file = scope.(File) and + startLine = 1 and + startColumn = 1 and + endLine = file.getNumberOfLines() and + endColumn = 999999 + } +} + +import GoCfg::ControlFlow::ViewCfgQuery diff --git a/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll b/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll index 6122ae6639f..d3047f8e81b 100644 --- a/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll +++ b/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll @@ -366,4 +366,6 @@ module ControlFlow { class ControlFlowNode = ControlFlow::Node; +class CfgScope = GoCfg::CfgScope; + class Write = ControlFlow::WriteNode; diff --git a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll index 30b2b3409a2..7686e40eaf6 100644 --- a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll +++ b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll @@ -26,6 +26,8 @@ module GoCfg { private import Cfg2 import Public + class CfgScope = Ast::Callable; + /** Holds if `e` has an implicit field selection at `index` for `implicitField`. */ predicate implicitFieldSelection(Go::AstNode e, int index, Go::Field implicitField) { Input::implicitFieldSelection(e, index, implicitField) @@ -206,7 +208,7 @@ module GoCfg { class Case extends AstNode { Case() { none() } - AstNode getAPattern() { none() } + AstNode getPattern(int index) { none() } Expr getGuard() { none() }