diff --git a/csharp/ql/lib/printDfg.ql b/csharp/ql/lib/printDfg.ql new file mode 100644 index 000000000000..8d8b6f9a4fa7 --- /dev/null +++ b/csharp/ql/lib/printDfg.ql @@ -0,0 +1,53 @@ +/** + * @name Print DFG + * @description Produces a representation of a file's Data Flow Graph. + * This query is used by the VS Code extension. + * @id cs/print-dfg + * @kind graph + * @tags ide-contextual-queries/print-dfg + */ + +import csharp +private import semmle.code.csharp.dataflow.internal.DataFlowImplSpecific as DF +private import semmle.code.csharp.dataflow.internal.TaintTrackingImplSpecific as TT +private import codeql.dataflow.PrintDfg +private import MakePrintDfg + +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 ViewDfgQueryInput implements ViewGraphQueryInputSig { + predicate selectedSourceFile = selectedSourceFileAlias/0; + + predicate selectedSourceLine = selectedSourceLineAlias/0; + + predicate selectedSourceColumn = selectedSourceColumnAlias/0; + + predicate callableSpan( + DF::CsharpDataFlow::DataFlowCallable callable, File file, int startLine, int startColumn, + int endLine, int endColumn + ) { + exists(Callable c | + c = callable.asCallable(_) and + file = c.getFile() and + callable.getLocation().getStartLine() = startLine and + callable.getLocation().getStartColumn() = startColumn and + exists(Location loc | + loc.getEndLine() = endLine and + loc.getEndColumn() = endColumn and + loc = c.getBody().getLocation() + ) + ) + } +} + +import ViewGraphQuery diff --git a/java/ql/lib/printCfg.ql b/java/ql/lib/printCfg.ql index 5e3cc22644ef..b176918ffa33 100644 --- a/java/ql/lib/printCfg.ql +++ b/java/ql/lib/printCfg.ql @@ -8,6 +8,7 @@ */ import java +import PrintCfg external string selectedSourceFile(); @@ -21,14 +22,14 @@ external int selectedSourceColumn(); private predicate selectedSourceColumnAlias = selectedSourceColumn/0; -module ViewCfgQueryInput implements ViewCfgQueryInputSig { +module ViewCfgQueryInput implements ViewGraphQueryInputSig { predicate selectedSourceFile = selectedSourceFileAlias/0; predicate selectedSourceLine = selectedSourceLineAlias/0; predicate selectedSourceColumn = selectedSourceColumnAlias/0; - predicate cfgScopeSpan( + predicate callableSpan( Callable callable, File file, int startLine, int startColumn, int endLine, int endColumn ) { file = callable.getFile() and @@ -42,4 +43,4 @@ module ViewCfgQueryInput implements ViewCfgQueryInputSig { } } -import ViewCfgQuery +import ViewGraphQuery diff --git a/java/ql/lib/printDfg.ql b/java/ql/lib/printDfg.ql new file mode 100644 index 000000000000..6913c9407d7d --- /dev/null +++ b/java/ql/lib/printDfg.ql @@ -0,0 +1,50 @@ +/** + * @name Print DFG + * @description Produces a representation of a file's Data Flow Graph. + * This query is used by the VS Code extension. + * @id java/print-cfg + * @kind graph + * @tags ide-contextual-queries/print-dfg + */ + +import java +private import semmle.code.java.dataflow.internal.DataFlowImplSpecific as DF +private import semmle.code.java.dataflow.internal.TaintTrackingImplSpecific as TT +private import codeql.dataflow.PrintDfg +private import MakePrintDfg + +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 ViewDfgQueryInput implements ViewGraphQueryInputSig { + predicate selectedSourceFile = selectedSourceFileAlias/0; + + predicate selectedSourceLine = selectedSourceLineAlias/0; + + predicate selectedSourceColumn = selectedSourceColumnAlias/0; + + predicate callableSpan( + DF::JavaDataFlow::DataFlowCallable callable, File file, int startLine, int startColumn, + int endLine, int endColumn + ) { + file = callable.asCallable().getFile() and + callable.getLocation().getStartLine() = startLine and + callable.getLocation().getStartColumn() = startColumn and + exists(Location loc | + loc.getEndLine() = endLine and + loc.getEndColumn() = endColumn and + loc = callable.asCallable().getBody().getLocation() + ) + } +} + +import ViewGraphQuery diff --git a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll index 64449b6f93d7..f477651b15db 100644 --- a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll +++ b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll @@ -1776,16 +1776,28 @@ class ConditionNode extends ControlFlow::Node { ExprParent getCondition() { result = this.asExpr() or result = this.asStmt() } } -private import codeql.controlflow.PrintGraph as PrintGraph +private import codeql.util.PrintGraph as PrintGraph private module PrintGraphInput implements PrintGraph::InputSig { private import java as J class Callable = J::Callable; - class ControlFlowNode = J::ControlFlowNode; + final private class FinalControlFlowNode = J::ControlFlowNode; - ControlFlowNode getASuccessor(ControlFlowNode n, SuccessorType t) { result = n.getASuccessor(t) } + class Node extends FinalControlFlowNode { + string getOrderDisambiguation() { result = "" } + } + + predicate edge(Node node1, string s, Node node2) { + exists(SuccessorType t | + node2 = node1.getASuccessor(t) and + if t instanceof DirectSuccessor then s = "" else s = t.toString() + ) + } } -import PrintGraph::PrintGraph +/** Provides utilities for visualising the CFG. */ +module PrintCfg { + import PrintGraph::PrintGraph +} diff --git a/javascript/ql/lib/printDfg.ql b/javascript/ql/lib/printDfg.ql new file mode 100644 index 000000000000..94f1e4bdf0f4 --- /dev/null +++ b/javascript/ql/lib/printDfg.ql @@ -0,0 +1,48 @@ +/** + * @name Print DFG + * @description Produces a representation of a file's Data Flow Graph. + * This query is used by the VS Code extension. + * @id js/print-dfg + * @kind graph + * @tags ide-contextual-queries/print-dfg + */ + +private import javascript +private import semmle.javascript.dataflow.internal.sharedlib.DataFlowArg +private import codeql.dataflow.PrintDfg +import MakePrintDfg + +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 ViewGraphQueryInputSig { + predicate selectedSourceFile = selectedSourceFileAlias/0; + + predicate selectedSourceLine = selectedSourceLineAlias/0; + + predicate selectedSourceColumn = selectedSourceColumnAlias/0; + + /** + * Holds if `callable` spans column `startColumn` of line `startLine` to + * column `endColumn` of line `endLine` in `file`. + */ + predicate callableSpan( + JSDataFlow::DataFlowCallable callable, File file, int startLine, int startColumn, int endLine, + int endColumn + ) { + callable + .getLocation() + .hasLocationInfo(file.getAbsolutePath(), startLine, startColumn, endLine, endColumn) + } +} + +import ViewGraphQuery diff --git a/ruby/ql/lib/ide-contextual-queries/printCfg.ql b/ruby/ql/lib/ide-contextual-queries/printCfg.ql index 1c4cec61a3ef..d6f5dbbcd35f 100644 --- a/ruby/ql/lib/ide-contextual-queries/printCfg.ql +++ b/ruby/ql/lib/ide-contextual-queries/printCfg.ql @@ -10,6 +10,7 @@ private import codeql.Locations private import codeql.ruby.controlflow.internal.ControlFlowGraphImpl private import codeql.ruby.controlflow.ControlFlowGraph +private import PrintCfg external string selectedSourceFile(); @@ -23,14 +24,14 @@ external int selectedSourceColumn(); private predicate selectedSourceColumnAlias = selectedSourceColumn/0; -module ViewCfgQueryInput implements ViewCfgQueryInputSig { +module ViewCfgQueryInput implements ViewGraphQueryInputSig { predicate selectedSourceFile = selectedSourceFileAlias/0; predicate selectedSourceLine = selectedSourceLineAlias/0; predicate selectedSourceColumn = selectedSourceColumnAlias/0; - predicate cfgScopeSpan( + predicate callableSpan( CfgScope scope, File file, int startLine, int startColumn, int endLine, int endColumn ) { file = scope.getFile() and @@ -38,4 +39,4 @@ module ViewCfgQueryInput implements ViewCfgQueryInputSig { } } -import ViewCfgQuery +import ViewGraphQuery diff --git a/ruby/ql/lib/ide-contextual-queries/printDfg.ql b/ruby/ql/lib/ide-contextual-queries/printDfg.ql new file mode 100644 index 000000000000..731925fe7d7c --- /dev/null +++ b/ruby/ql/lib/ide-contextual-queries/printDfg.ql @@ -0,0 +1,44 @@ +/** + * @name Print DFG + * @description Produces a representation of a file's Data Flow Graph. + * This query is used by the VS Code extension. + * @id rb/print-dfg + * @kind graph + * @tags ide-contextual-queries/print-dfg + */ + +private import codeql.Locations +private import codeql.ruby.dataflow.internal.DataFlowImplSpecific as DF +private import codeql.ruby.dataflow.internal.TaintTrackingImplSpecific as TT +private import codeql.dataflow.PrintDfg +private import MakePrintDfg + +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 ViewDfgQueryInput implements ViewGraphQueryInputSig { + predicate selectedSourceFile = selectedSourceFileAlias/0; + + predicate selectedSourceLine = selectedSourceLineAlias/0; + + predicate selectedSourceColumn = selectedSourceColumnAlias/0; + + predicate callableSpan( + DF::RubyDataFlow::DataFlowCallable callable, File file, int startLine, int startColumn, + int endLine, int endColumn + ) { + file = callable.asCfgScope().getFile() and + callable.getLocation().hasLocationInfo(_, startLine, startColumn, endLine, endColumn) + } +} + +import ViewGraphQuery diff --git a/rust/ql/lib/ide-contextual-queries/PrintCfg.ql b/rust/ql/lib/ide-contextual-queries/PrintCfg.ql index e7b25ea8df8e..8159daa22808 100644 --- a/rust/ql/lib/ide-contextual-queries/PrintCfg.ql +++ b/rust/ql/lib/ide-contextual-queries/PrintCfg.ql @@ -10,6 +10,7 @@ private import codeql.files.FileSystem private import codeql.rust.controlflow.internal.ControlFlowGraphImpl private import codeql.rust.controlflow.ControlFlowGraph +private import PrintCfg /** * Gets the source file to generate a CFG from. @@ -32,14 +33,14 @@ external int selectedSourceColumn(); private predicate selectedSourceColumnAlias = selectedSourceColumn/0; -private module ViewCfgQueryInput implements ViewCfgQueryInputSig { +private module ViewCfgQueryInput implements ViewGraphQueryInputSig { predicate selectedSourceFile = selectedSourceFileAlias/0; predicate selectedSourceLine = selectedSourceLineAlias/0; predicate selectedSourceColumn = selectedSourceColumnAlias/0; - predicate cfgScopeSpan( + predicate callableSpan( CfgScope scope, File file, int startLine, int startColumn, int endLine, int endColumn ) { file = scope.getFile() and @@ -47,4 +48,4 @@ private module ViewCfgQueryInput implements ViewCfgQueryInputSig { } } -import ViewCfgQuery +import ViewGraphQuery diff --git a/rust/ql/lib/ide-contextual-queries/PrintDfg.ql b/rust/ql/lib/ide-contextual-queries/PrintDfg.ql new file mode 100644 index 000000000000..8121bfbbbab2 --- /dev/null +++ b/rust/ql/lib/ide-contextual-queries/PrintDfg.ql @@ -0,0 +1,44 @@ +/** + * @name Print DFG + * @description Produces a representation of a file's Data Flow Graph. + * This query is used by the VS Code extension. + * @id rust/print-dfg + * @kind graph + * @tags ide-contextual-queries/print-dfg + */ + +private import rust +private import codeql.rust.dataflow.internal.DataFlowImpl as DF +private import codeql.rust.dataflow.internal.TaintTrackingImpl as TT +private import codeql.dataflow.PrintDfg +private import MakePrintDfg + +external string selectedSourceFile(); + +private predicate selectedSourceFileAlias = selectedSourceFile/0; + +external int selectedSourceLine(); + +private predicate selectedSourceLineAlias = selectedSourceLine/0; + +external int selectedSourceColumn(); + +private predicate selectedSourceColumnAlias = selectedSourceColumn/0; + +private module ViewDfgQueryInput implements ViewGraphQueryInputSig { + predicate selectedSourceFile = selectedSourceFileAlias/0; + + predicate selectedSourceLine = selectedSourceLineAlias/0; + + predicate selectedSourceColumn = selectedSourceColumnAlias/0; + + predicate callableSpan( + DF::RustDataFlow::DataFlowCallable callable, File file, int startLine, int startColumn, + int endLine, int endColumn + ) { + file = callable.asCfgScope().getFile() and + callable.getLocation().hasLocationInfo(_, startLine, startColumn, endLine, endColumn) + } +} + +import ViewGraphQuery diff --git a/shared/controlflow/codeql/controlflow/Cfg.qll b/shared/controlflow/codeql/controlflow/Cfg.qll index 157bf0ffd4f3..0cff98ef4be9 100644 --- a/shared/controlflow/codeql/controlflow/Cfg.qll +++ b/shared/controlflow/codeql/controlflow/Cfg.qll @@ -1313,19 +1313,29 @@ module MakeWithSplitting< } } - private import PrintGraph as Pp + private import codeql.util.PrintGraph as Pp + + final private class FinalNode = Node; private module PrintGraphInput implements Pp::InputSig { class Callable = CfgScope; - class ControlFlowNode = Node; + class Node extends FinalNode { + string getOrderDisambiguation() { result = "" } + } - ControlFlowNode getASuccessor(ControlFlowNode n, SuccessorType t) { - result = n.getASuccessor(t) + predicate edge(Node node1, string label, Node node2) { + exists(SuccessorType t | + node2 = node1.getASuccessor(t) and + if t instanceof DirectSuccessor then label = "" else label = t.toString() + ) } } - import Pp::PrintGraph + /** Provides utilities for visualising the CFG. */ + module PrintCfg { + import Pp::PrintGraph + } /** Provides a set of consistency queries. */ module Consistency { diff --git a/shared/dataflow/codeql/dataflow/DataFlow.qll b/shared/dataflow/codeql/dataflow/DataFlow.qll index 7f9c0194374b..3a7afd7e873e 100644 --- a/shared/dataflow/codeql/dataflow/DataFlow.qll +++ b/shared/dataflow/codeql/dataflow/DataFlow.qll @@ -361,6 +361,12 @@ signature module InputSig { * visible. */ default predicate isEvaluatingInOverlay() { none() } + + /** + * Gets a string to distinguish nodes that have the same location and toString value, + * for use when generating graphs with `PrintDfg.qll`. + */ + default string nodeGetOrderDisambiguation(Node node) { result = "" } } module Configs Lang> { diff --git a/shared/dataflow/codeql/dataflow/PrintDfg.qll b/shared/dataflow/codeql/dataflow/PrintDfg.qll new file mode 100644 index 000000000000..5b3a836d7050 --- /dev/null +++ b/shared/dataflow/codeql/dataflow/PrintDfg.qll @@ -0,0 +1,45 @@ +/** + * Provides a module for implementing the `View DFG` query based on inputs to the data flow library. + */ + +private import codeql.util.Location +private import codeql.dataflow.DataFlow as DF +private import codeql.dataflow.TaintTracking as TT + +module MakePrintDfg< + LocationSig Location, DF::InputSig DataFlowLang, + TT::InputSig TaintTrackingLang> +{ + private import DataFlowLang + private import codeql.util.PrintGraph as Pp + + final private class FinalNode = Node; + + private module PrintGraphInput implements Pp::InputSig { + class Callable = DataFlowLang::DataFlowCallable; + + class Node extends FinalNode { + string getOrderDisambiguation() { result = DataFlowLang::nodeGetOrderDisambiguation(this) } + + Callable getEnclosingCallable() { result = DataFlowLang::nodeGetEnclosingCallable(this) } + } + + predicate edge(Node node1, string label, Node node2) { + simpleLocalFlowStep(node1, node2, _) and label = "value" + or + jumpStep(node1, node2) and label = "jump" + or + TaintTrackingLang::defaultAdditionalTaintStep(node1, node2, _) and label = "taint" + or + exists(ContentSet c | + readStep(node1, c, node2) and label = "read[" + c.toString() + "]" + or + storeStep(node1, c, node2) and label = "store[" + c.toString() + "]" + ) + or + node1 = node2.(PostUpdateNode).getPreUpdateNode() and label = "post-update" + } + } + + import Pp::PrintGraph +} diff --git a/shared/controlflow/codeql/controlflow/PrintGraph.qll b/shared/util/codeql/util/PrintGraph.qll similarity index 71% rename from shared/controlflow/codeql/controlflow/PrintGraph.qll rename to shared/util/codeql/util/PrintGraph.qll index c4a942feab23..bbeb9332ed8c 100644 --- a/shared/controlflow/codeql/controlflow/PrintGraph.qll +++ b/shared/util/codeql/util/PrintGraph.qll @@ -1,6 +1,6 @@ /** - * Provides modules for printing control flow graphs in VSCode via the "View - * CFG" query. Also provides modules for printing control flow graphs in tests + * Provides modules for printing control flow and data flow graphs in VSCode via the + * "View CFG/DFG" queries. Also provides modules for printing such graphs in tests * and as Mermaid diagrams. */ overlay[local?] @@ -8,47 +8,43 @@ module; private import codeql.util.FileSystem private import codeql.util.Location -private import SuccessorType signature module InputSig { class Callable; - class ControlFlowNode { + class Node { Callable getEnclosingCallable(); Location getLocation(); string toString(); + + /** Gets a string to distinguish nodes that have the same location and toString value. */ + string getOrderDisambiguation(); } - ControlFlowNode getASuccessor(ControlFlowNode n, SuccessorType t); + predicate edge(Node node1, string label, Node node2); } -/** Provides modules for printing control flow graphs. */ +/** Provides modules for printing flow graphs. */ module PrintGraph Input> { private import Input /** A node to be included in the output of `TestOutput`. */ - signature class RelevantNodeSig extends ControlFlowNode; + signature class RelevantNodeSig extends Node; /** - * Import this module into a `.ql` file to output a CFG. The + * Import this module into a `.ql` file to output a graph. The * graph is restricted to nodes from `RelevantNode`. */ module TestOutput { - /** Holds if `pred -> succ` is an edge in the CFG. */ + /** Holds if `pred -> succ` is an edge in the graph. */ query predicate edges(RelevantNode pred, RelevantNode succ, string label) { - label = - strictconcat(SuccessorType t, string s | - succ = getASuccessor(pred, t) and - if t instanceof DirectSuccessor then s = "" else s = t.toString() - | - s, ", " order by s - ) + label = strictconcat(string s | edge(pred, s, succ) | s, ", " order by s) } /** - * Provides logic for representing a CFG as a [Mermaid diagram](https://mermaid.js.org/). + * Provides logic for representing a graph as a [Mermaid diagram](https://mermaid.js.org/). */ module Mermaid { private string nodeId(RelevantNode n) { @@ -60,7 +56,10 @@ module PrintGraph Input> { p.getLocation() .hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn) | - p order by filePath, startLine, startColumn, endLine, endColumn, p.toString() + p + order by + filePath, startLine, startColumn, endLine, endColumn, p.toString(), + p.getOrderDisambiguation() ) ).toString() } @@ -94,7 +93,8 @@ module PrintGraph Input> { | edge, "\n" order by - filePath, startLine, startColumn, endLine, endColumn, pred.toString() + filePath, startLine, startColumn, endLine, endColumn, pred.toString(), + pred.getOrderDisambiguation() ) } @@ -103,8 +103,8 @@ module PrintGraph Input> { } } - /** Provides the input to `ViewCfgQuery`. */ - signature module ViewCfgQueryInputSig { + /** Provides the input to `ViewGraphQuery`. */ + signature module ViewGraphQueryInputSig { /** Gets the source file selected in the IDE. Should be an `external` predicate. */ string selectedSourceFile(); @@ -118,15 +118,15 @@ module PrintGraph Input> { * Holds if `callable` spans column `startColumn` of line `startLine` to * column `endColumn` of line `endLine` in `file`. */ - predicate cfgScopeSpan( + predicate callableSpan( Callable callable, File file, int startLine, int startColumn, int endLine, int endColumn ); } /** - * Provides an implementation for a `View CFG` query. + * Provides an implementation for a `View CFG` or `View DFG` query. * - * Import this module into a `.ql` that looks like + * Import this module into a `.ql` that looks like (for the `View CFG` query): * * ```ql * @name Print CFG @@ -136,15 +136,17 @@ module PrintGraph Input> { * @kind graph * @tags ide-contextual-queries/print-cfg * ``` + * + * For the `View DFG` query replace "cfg" with "dfg" above and "control flow" with "data flow". */ - module ViewCfgQuery ViewCfgQueryInput> { - private import ViewCfgQueryInput + module ViewGraphQuery ViewGraphQueryInput> { + private import ViewGraphQueryInput bindingset[file, line, column] private Callable smallestEnclosingScope(File file, int line, int column) { result = min(Callable callable, int startLine, int startColumn, int endLine, int endColumn | - cfgScopeSpan(callable, file, startLine, startColumn, endLine, endColumn) and + callableSpan(callable, file, startLine, startColumn, endLine, endColumn) and ( startLine < line or @@ -162,23 +164,21 @@ module PrintGraph Input> { private import IdeContextual - final private class FinalControlFlowNode = ControlFlowNode; + final private class FinalNode = Node; - private class RelevantNode extends FinalControlFlowNode { + private class RelevantNode extends FinalNode { RelevantNode() { this.getEnclosingCallable() = smallestEnclosingScope(getFileBySourceArchiveName(selectedSourceFile()), selectedSourceLine(), selectedSourceColumn()) } - - string getOrderDisambiguation() { result = "" } } private module Output = TestOutput; import Output::Mermaid - /** Holds if `pred` -> `succ` is an edge in the CFG. */ + /** Holds if `pred` -> `succ` is an edge in the graph. */ query predicate edges(RelevantNode pred, RelevantNode succ, string attr, string val) { attr = "semmle.label" and Output::edges(pred, succ, val) diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/PrintCFG.ql b/swift/ql/lib/codeql/swift/controlflow/internal/PrintCFG.ql index 2f9a0572111c..58c742a71e53 100644 --- a/swift/ql/lib/codeql/swift/controlflow/internal/PrintCFG.ql +++ b/swift/ql/lib/codeql/swift/controlflow/internal/PrintCFG.ql @@ -33,14 +33,14 @@ external int selectedSourceColumn(); private predicate selectedSourceColumnAlias = selectedSourceColumn/0; -module ViewCfgQueryInput implements Impl::ViewCfgQueryInputSig { +module ViewCfgQueryInput implements Impl::PrintCfg::ViewGraphQueryInputSig { predicate selectedSourceFile = selectedSourceFileAlias/0; predicate selectedSourceLine = selectedSourceLineAlias/0; predicate selectedSourceColumn = selectedSourceColumnAlias/0; - predicate cfgScopeSpan( + predicate callableSpan( CfgInput::CfgScope scope, File file, int startLine, int startColumn, int endLine, int endColumn ) { file = scope.getFile() and @@ -48,4 +48,4 @@ module ViewCfgQueryInput implements Impl::ViewCfgQueryInputSig { } } -import Impl::ViewCfgQuery +import Impl::PrintCfg::ViewGraphQuery