Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit 6c4a1d0

Browse files
authored
Merge pull request #264 from smowton/smowton/feature/printast-restrict-files
PrintAst: improve support for restricting subsets of the AST to print
2 parents 3018874 + f8d141f commit 6c4a1d0

14 files changed

+982
-8
lines changed

ql/src/printAst.ql

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ external string selectedSourceFile();
2020
* Hook to customize the functions printed by this query.
2121
*/
2222
class Cfg extends PrintAstConfiguration {
23-
override predicate shouldPrintFunction(FuncDef func) {
24-
func.getFile() = getEncodedFile(selectedSourceFile())
25-
}
23+
override predicate shouldPrintFunction(FuncDecl func) { shouldPrintFile(func.getFile()) }
24+
25+
override predicate shouldPrintFile(File file) { file = getEncodedFile(selectedSourceFile()) }
26+
27+
override predicate shouldPrintComments(File file) { none() }
2628
}

ql/src/semmle/go/PrintAst.ql

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,9 @@ import PrintAst
1212
* Hook to customize the functions printed by this query.
1313
*/
1414
class Cfg extends PrintAstConfiguration {
15-
override predicate shouldPrintFunction(FuncDef func) { any() }
15+
override predicate shouldPrintFunction(FuncDecl func) { any() }
16+
17+
override predicate shouldPrintFile(File file) { any() }
18+
19+
override predicate shouldPrintComments(File file) { any() }
1620
}

ql/src/semmle/go/PrintAst.qll

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
import go
66

77
/**
8-
* Hook to customize the functions printed by this module.
8+
* Hook to customize the files and functions printed by this module.
9+
*
10+
* For an AstNode to be printed, it always requires `shouldPrintFile(f)` to hold
11+
* for its containing file `f`, and additionally requires `shouldPrintFunction(fun)`
12+
* to hold if it is, or is a child of, function `fun`.
913
*/
1014
class PrintAstConfiguration extends string {
1115
/**
@@ -17,20 +21,48 @@ class PrintAstConfiguration extends string {
1721
* Holds if the AST for `func` should be printed. By default, holds for all
1822
* functions.
1923
*/
20-
predicate shouldPrintFunction(FuncDef func) { any() }
24+
predicate shouldPrintFunction(FuncDecl func) { any() }
25+
26+
/**
27+
* Holds if the AST for `file` should be printed. By default, holds for all
28+
* files.
29+
*/
30+
predicate shouldPrintFile(File file) { any() }
31+
32+
/**
33+
* Holds if the AST for `file` should include comments. By default, holds for all
34+
* files.
35+
*/
36+
predicate shouldPrintComments(File file) { any() }
2137
}
2238

2339
private predicate shouldPrintFunction(FuncDef func) {
2440
exists(PrintAstConfiguration config | config.shouldPrintFunction(func))
2541
}
2642

43+
private predicate shouldPrintFile(File file) {
44+
exists(PrintAstConfiguration config | config.shouldPrintFile(file))
45+
}
46+
47+
private predicate shouldPrintComments(File file) {
48+
exists(PrintAstConfiguration config | config.shouldPrintComments(file))
49+
}
50+
51+
private FuncDecl getEnclosingFunctionDecl(AstNode n) { result = n.getParent*() }
52+
2753
/**
2854
* An AST node that should be printed.
2955
*/
3056
private newtype TPrintAstNode =
3157
TAstNode(AstNode ast) {
32-
// Do print ast nodes without an enclosing function, e.g. file headers
33-
forall(FuncDef f | f = ast.getEnclosingFunction() | shouldPrintFunction(f))
58+
shouldPrintFile(ast.getFile()) and
59+
// Do print ast nodes without an enclosing function, e.g. file headers, that are not otherwise excluded
60+
forall(FuncDecl f | f = getEnclosingFunctionDecl(ast) | shouldPrintFunction(f)) and
61+
(
62+
shouldPrintComments(ast.getFile())
63+
or
64+
not ast instanceof Comment and not ast instanceof CommentGroup
65+
)
3466
}
3567

3668
/**
@@ -149,6 +181,19 @@ class ExprNode extends BaseAstNode {
149181
class FileNode extends BaseAstNode {
150182
override File ast;
151183

184+
private string getRelativePath() { result = ast.getRelativePath() }
185+
186+
private int getSortOrder() {
187+
rank[result](FileNode fn | any() | fn order by fn.getRelativePath()) = this
188+
}
189+
190+
override string getProperty(string key) {
191+
result = super.getProperty(key)
192+
or
193+
key = "semmle.order" and
194+
result = getSortOrder().toString()
195+
}
196+
152197
/**
153198
* Gets the string representation of this File. Note explicitly using a relative path
154199
* like this rather than absolute as per default for the File class is a workaround for

ql/test/library-tests/semmle/go/PrintAst/PrintAst.expected

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
go.mod:
2+
# 0| [GoModFile] library-tests/semmle/go/PrintAst/go.mod
3+
# 1| 0: [GoModModuleLine] go.mod module line
4+
# 3| 1: [GoModGoLine] go.mod go line
15
input.go:
26
# 0| [File] library-tests/semmle/go/PrintAst/input.go
37
# 5| 0: [CommentGroup] comment group
@@ -592,3 +596,55 @@ input.go:
592596
# 145| Type = []int
593597
# 145| 1: [BlockStmt] block statement
594598
# 1| 18: [Ident] main
599+
other.go:
600+
# 0| [File] library-tests/semmle/go/PrintAst/other.go
601+
# 3| 0: [FuncDecl] function declaration
602+
# 3| 0: [FunctionName, Ident] main
603+
# 3| Type = func()
604+
# 3| 1: [FuncTypeExpr] function type
605+
# 3| 2: [BlockStmt] block statement
606+
# 5| 1: [FuncDecl] function declaration
607+
# 5| 0: [FunctionName, Ident] f
608+
# 5| Type = func()
609+
# 5| 1: [FuncTypeExpr] function type
610+
# 5| 2: [BlockStmt] block statement
611+
# 6| 2: [FuncDecl] function declaration
612+
# 6| 0: [FunctionName, Ident] g
613+
# 6| Type = func()
614+
# 6| 1: [FuncTypeExpr] function type
615+
# 6| 2: [BlockStmt] block statement
616+
# 8| 3: [FuncDecl] function declaration
617+
# 8| 0: [FunctionName, Ident] hasNested
618+
# 8| Type = func()
619+
# 8| 1: [FuncTypeExpr] function type
620+
# 8| 2: [BlockStmt] block statement
621+
# 10| 0: [DefineStmt] ... := ...
622+
# 10| 0: [Ident, VariableName] myNested
623+
# 10| Type = func() int
624+
# 10| 1: [FuncLit] function literal
625+
# 10| Type = func() int
626+
# 10| 0: [FuncTypeExpr] function type
627+
# 10| Type = func() int
628+
# 10| 0: [ResultVariableDecl] result variable declaration
629+
# 10| 0: [Ident, TypeName] int
630+
# 10| Type = int
631+
# 10| 1: [BlockStmt] block statement
632+
# 10| 0: [ReturnStmt] return statement
633+
# 10| 0: [IntLit] 1
634+
# 10| Type = int
635+
# 10| Value = [IntLit] 1
636+
# 11| 1: [ExprStmt] expression statement
637+
# 11| 0: [CallExpr] call to myNested
638+
# 11| Type = int
639+
# 11| 0: [Ident, VariableName] myNested
640+
# 11| Type = func() int
641+
# 15| 4: [VarDecl] variable declaration
642+
# 15| 0: [ValueSpec] value declaration specifier
643+
# 15| 0: [Ident, VariableName] x
644+
# 15| Type = int
645+
# 15| 1: [Ident, TypeName] int
646+
# 15| Type = int
647+
# 15| 2: [IntLit] 0
648+
# 15| Type = int
649+
# 15| Value = [IntLit] 0
650+
# 1| 5: [Ident] main

0 commit comments

Comments
 (0)