Skip to content

Commit b1dff3e

Browse files
committed
Fix go PrintAST && java PrintCFG queries
Fixes "tools" queries in response to breaking changes from recent upgrade to CodeQL v2.25.0 and associated pack dependency upgrades, including fixes for: - `server/ql/go/tools/{src,test}/PrintAST/**` - `server/ql/java/tools/{src,test}/PrintCFG/**` Updates language-specific AST resource definitions in order to reflect actual AST nodes for current (v2.25.0) version of CodeQL and associated pack dependencies, including updates for MCP resources: - `go_ast` - `java_ast`
1 parent 0cb609d commit b1dff3e

File tree

8 files changed

+608
-278
lines changed

8 files changed

+608
-278
lines changed

server/dist/codeql-development-mcp-server.js

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

server/dist/codeql-development-mcp-server.js.map

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/ql/go/tools/src/PrintAST/PrintAST.ql

Lines changed: 129 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
*/
88

99
import go
10-
import semmle.go.PrintAst
1110

1211
/**
1312
* Gets the source files to generate AST from.
@@ -34,25 +33,142 @@ File getSelectedFile() {
3433
// Match by file name if no path separators
3534
(not selectedFile.matches("%/%") and result.getBaseName() = selectedFile) or
3635
// Match by ending path component
37-
result.getAbsolutePath().suffix(result.getAbsolutePath().length() - selectedFile.length()) = selectedFile
36+
result.getAbsolutePath().suffix(result.getAbsolutePath().length() - selectedFile.length()) =
37+
selectedFile
3838
)
3939
)
4040
}
4141

4242
/**
43-
* Configuration for PrintAST that uses external predicates to specify source files.
44-
* Falls back to test file selection when external predicates are not available.
43+
* Holds if the given file should be printed.
44+
* Uses the external predicate if available, otherwise falls back to test files.
4545
*/
46-
class Cfg extends PrintAstConfiguration {
47-
override predicate shouldPrintFunction(FuncDecl func) { this.shouldPrintFile(func.getFile()) }
46+
private predicate isSelectedFile(File file) {
47+
file = getSelectedFile()
48+
or
49+
not exists(getSelectedFile()) and file.getBaseName() = "Example1.go"
50+
}
51+
52+
// Standalone PrintAST implementation for Go.
53+
//
54+
// This avoids extending the library's `PrintAstConfiguration` (which is inside
55+
// an `overlay[local]` module in `go-all`) by directly using the Go AST API.
56+
// File filtering is applied at the source level for efficiency.
57+
58+
/** Gets the enclosing function declaration for `n`, if any. */
59+
private FuncDecl getEnclosingFunctionDecl(AstNode n) { result = n.getParent*() }
60+
61+
/**
62+
* Holds if `ast` should be included in the printed AST.
63+
* Restricts to selected files and excludes comments for deterministic output.
64+
*/
65+
private predicate shouldPrint(AstNode ast) {
66+
isSelectedFile(ast.getFile()) and
67+
// Print nodes without an enclosing function (e.g. file headers)
68+
forall(FuncDecl f | f = getEnclosingFunctionDecl(ast) | isSelectedFile(f.getFile())) and
69+
// Exclude comments for deterministic output
70+
not ast instanceof Comment and
71+
not ast instanceof CommentGroup and
72+
exists(ast.getLocation())
73+
}
4874

49-
override predicate shouldPrintFile(File file) {
50-
// Use external predicate if available
51-
file = getSelectedFile()
75+
/** Gets the QL class label for an AST node. */
76+
private string qlClass(AstNode el) {
77+
result = "[" + concat(el.getAPrimaryQlClass(), ", ") + "] "
78+
}
79+
80+
/** Gets the default string representation for an AST node. */
81+
private string nodeToString(AstNode ast) {
82+
if ast instanceof File
83+
then result = qlClass(ast) + ast.(File).getRelativePath()
84+
else result = qlClass(ast) + ast.toString()
85+
}
86+
87+
/**
88+
* Gets the child at `childIndex` for `ast`, with special handling
89+
* for `File` nodes (package name expression is moved to index 0).
90+
* Comments are excluded from the child list.
91+
*/
92+
private AstNode getChild(AstNode ast, int childIndex) {
93+
if ast instanceof File and exists(ast.(File).getPackageNameExpr())
94+
then
95+
exists(AstNode packageNode, int oldPackageIndex |
96+
ast.getUniquelyNumberedChild(oldPackageIndex) = packageNode and
97+
packageNode = ast.(File).getPackageNameExpr() and
98+
(
99+
childIndex = 0 and result = packageNode
100+
or
101+
result =
102+
rank[childIndex](AstNode node, int i |
103+
node = ast.getUniquelyNumberedChild(i) and
104+
i != oldPackageIndex and
105+
not node instanceof Comment and
106+
not node instanceof CommentGroup
107+
|
108+
node order by i
109+
)
110+
)
111+
)
112+
else (
113+
result =
114+
rank[childIndex](AstNode node, int i |
115+
node = ast.getUniquelyNumberedChild(i) and
116+
not node instanceof Comment and
117+
not node instanceof CommentGroup
118+
|
119+
node order by i
120+
)
121+
)
122+
}
123+
124+
/** Gets the edge label from `ast` to its child at `childIndex`. */
125+
private string getChildEdgeLabel(AstNode ast, int childIndex) {
126+
exists(getChild(ast, childIndex)) and
127+
if
128+
ast instanceof File and
129+
exists(ast.(File).getPackageNameExpr()) and
130+
getChild(ast, childIndex) = ast.(File).getPackageNameExpr()
131+
then result = "package"
132+
else result = childIndex.toString()
133+
}
134+
135+
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
136+
query predicate nodes(AstNode node, string key, string value) {
137+
shouldPrint(node) and
138+
(
139+
key = "semmle.label" and value = nodeToString(node)
140+
or
141+
node instanceof Expr and
142+
(
143+
key = "Value" and
144+
value = qlClass(node) + node.(Expr).getExactValue()
145+
or
146+
key = "Type" and
147+
not node.(Expr).getType() instanceof InvalidType and
148+
value = node.(Expr).getType().pp()
149+
)
52150
or
53-
// Fallback for unit tests: include specific test files
54-
(not exists(getSelectedFile()) and file.getBaseName() = "Example1.go")
55-
}
151+
node instanceof File and
152+
key = "semmle.order" and
153+
value = any(int i | node = rank[i](File fn | isSelectedFile(fn) | fn order by fn.getRelativePath()) | i).toString()
154+
)
155+
}
156+
157+
/** Holds if `target` is a child of `source` in the AST. */
158+
query predicate edges(AstNode source, AstNode target, string key, string value) {
159+
shouldPrint(source) and
160+
shouldPrint(target) and
161+
exists(int childIndex |
162+
target = getChild(source, childIndex) and
163+
(
164+
key = "semmle.label" and value = getChildEdgeLabel(source, childIndex)
165+
or
166+
key = "semmle.order" and value = childIndex.toString()
167+
)
168+
)
169+
}
56170

57-
override predicate shouldPrintComments(File file) { none() }
171+
/** Holds if property `key` of the graph has the given `value`. */
172+
query predicate graphProperties(string key, string value) {
173+
key = "semmle.graphKind" and value = "tree"
58174
}

0 commit comments

Comments
 (0)