From c30d198f3d62a9953ff634ced12b0776d9df6e00 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 21 Jul 2020 16:47:49 +0100 Subject: [PATCH] Switch to using top-level function declarations to filter PrintAst This means it's no longer possible to ask for the AST of a function literal, but this is hopefully a niche use-case that we can add if and when there is demand. --- ql/src/printAst.ql | 2 +- ql/src/semmle/go/PrintAst.ql | 2 +- ql/src/semmle/go/PrintAst.qll | 9 +-- .../semmle/go/PrintAst/PrintAst.expected | 45 ++++++++++--- .../PrintAst/PrintAstExcludeComments.expected | 45 ++++++++++--- .../go/PrintAst/PrintAstExcludeComments.ql | 2 +- .../PrintAst/PrintAstNestedFunction.expected | 67 +++++++++++++++++++ .../go/PrintAst/PrintAstNestedFunction.ql | 14 ++++ .../go/PrintAst/PrintAstRestrictFile.expected | 45 ++++++++++--- .../go/PrintAst/PrintAstRestrictFile.ql | 2 +- .../PrintAstRestrictFunction.expected | 20 +++--- .../go/PrintAst/PrintAstRestrictFunction.ql | 2 +- .../library-tests/semmle/go/PrintAst/other.go | 7 ++ 13 files changed, 211 insertions(+), 51 deletions(-) create mode 100644 ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.expected create mode 100644 ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.ql diff --git a/ql/src/printAst.ql b/ql/src/printAst.ql index e5b36e73fe3..e74ddd2cc43 100644 --- a/ql/src/printAst.ql +++ b/ql/src/printAst.ql @@ -20,7 +20,7 @@ external string selectedSourceFile(); * Hook to customize the functions printed by this query. */ class Cfg extends PrintAstConfiguration { - override predicate shouldPrintFunction(FuncDef func) { shouldPrintFile(func.getFile()) } + override predicate shouldPrintFunction(FuncDecl func) { shouldPrintFile(func.getFile()) } override predicate shouldPrintFile(File file) { file = getEncodedFile(selectedSourceFile()) } diff --git a/ql/src/semmle/go/PrintAst.ql b/ql/src/semmle/go/PrintAst.ql index b564f7d1eba..23b6b123b06 100644 --- a/ql/src/semmle/go/PrintAst.ql +++ b/ql/src/semmle/go/PrintAst.ql @@ -12,7 +12,7 @@ import PrintAst * Hook to customize the functions printed by this query. */ class Cfg extends PrintAstConfiguration { - override predicate shouldPrintFunction(FuncDef func) { any() } + override predicate shouldPrintFunction(FuncDecl func) { any() } override predicate shouldPrintFile(File file) { any() } diff --git a/ql/src/semmle/go/PrintAst.qll b/ql/src/semmle/go/PrintAst.qll index a78448b19e3..ba11d76977e 100644 --- a/ql/src/semmle/go/PrintAst.qll +++ b/ql/src/semmle/go/PrintAst.qll @@ -21,7 +21,7 @@ class PrintAstConfiguration extends string { * Holds if the AST for `func` should be printed. By default, holds for all * functions. */ - predicate shouldPrintFunction(FuncDef func) { any() } + predicate shouldPrintFunction(FuncDecl func) { any() } /** * Holds if the AST for `file` should be printed. By default, holds for all @@ -48,10 +48,7 @@ private predicate shouldPrintComments(File file) { exists(PrintAstConfiguration config | config.shouldPrintComments(file)) } -private FuncDef getEnclosingFunction(AstNode n) { - result = n or - result = n.getEnclosingFunction() -} +private FuncDecl getEnclosingFunctionDecl(AstNode n) { result = n.getParent*() } /** * An AST node that should be printed. @@ -60,7 +57,7 @@ private newtype TPrintAstNode = TAstNode(AstNode ast) { shouldPrintFile(ast.getFile()) and // Do print ast nodes without an enclosing function, e.g. file headers, that are not otherwise excluded - forall(FuncDef f | f = getEnclosingFunction(ast) | shouldPrintFunction(f)) and + forall(FuncDecl f | f = getEnclosingFunctionDecl(ast) | shouldPrintFunction(f)) and ( shouldPrintComments(ast.getFile()) or diff --git a/ql/test/library-tests/semmle/go/PrintAst/PrintAst.expected b/ql/test/library-tests/semmle/go/PrintAst/PrintAst.expected index 3ac5a533462..639f3d5ae8f 100644 --- a/ql/test/library-tests/semmle/go/PrintAst/PrintAst.expected +++ b/ql/test/library-tests/semmle/go/PrintAst/PrintAst.expected @@ -15,16 +15,41 @@ other.go: # 6| Type = func() # 6| 1: [FuncTypeExpr] function type # 6| 2: [BlockStmt] block statement -# 8| 3: [VarDecl] variable declaration -# 8| 0: [ValueSpec] value declaration specifier -# 8| 0: [Ident, VariableName] x -# 8| Type = int -# 8| 1: [Ident, TypeName] int -# 8| Type = int -# 8| 2: [IntLit] 0 -# 8| Type = int -# 8| Value = [IntLit] 0 -# 1| 4: [Ident] main +# 8| 3: [FuncDecl] function declaration +# 8| 0: [FunctionName, Ident] hasNested +# 8| Type = func() +# 8| 1: [FuncTypeExpr] function type +# 8| 2: [BlockStmt] block statement +# 10| 0: [DefineStmt] ... := ... +# 10| 0: [Ident, VariableName] myNested +# 10| Type = func() int +# 10| 1: [FuncLit] function literal +# 10| Type = func() int +# 10| 0: [FuncTypeExpr] function type +# 10| Type = func() int +# 10| 0: [ResultVariableDecl] result variable declaration +# 10| 0: [Ident, TypeName] int +# 10| Type = int +# 10| 1: [BlockStmt] block statement +# 10| 0: [ReturnStmt] return statement +# 10| 0: [IntLit] 1 +# 10| Type = int +# 10| Value = [IntLit] 1 +# 11| 1: [ExprStmt] expression statement +# 11| 0: [CallExpr] call to myNested +# 11| Type = int +# 11| 0: [Ident, VariableName] myNested +# 11| Type = func() int +# 15| 4: [VarDecl] variable declaration +# 15| 0: [ValueSpec] value declaration specifier +# 15| 0: [Ident, VariableName] x +# 15| Type = int +# 15| 1: [Ident, TypeName] int +# 15| Type = int +# 15| 2: [IntLit] 0 +# 15| Type = int +# 15| Value = [IntLit] 0 +# 1| 5: [Ident] main go.mod: # 0| [GoModFile] library-tests/semmle/go/PrintAst/go.mod # 1| 0: [GoModModuleLine] go.mod module line diff --git a/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.expected b/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.expected index ed71d23e1bb..64d56749766 100644 --- a/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.expected +++ b/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.expected @@ -15,16 +15,41 @@ other.go: # 6| Type = func() # 6| 1: [FuncTypeExpr] function type # 6| 2: [BlockStmt] block statement -# 8| 3: [VarDecl] variable declaration -# 8| 0: [ValueSpec] value declaration specifier -# 8| 0: [Ident, VariableName] x -# 8| Type = int -# 8| 1: [Ident, TypeName] int -# 8| Type = int -# 8| 2: [IntLit] 0 -# 8| Type = int -# 8| Value = [IntLit] 0 -# 1| 4: [Ident] main +# 8| 3: [FuncDecl] function declaration +# 8| 0: [FunctionName, Ident] hasNested +# 8| Type = func() +# 8| 1: [FuncTypeExpr] function type +# 8| 2: [BlockStmt] block statement +# 10| 0: [DefineStmt] ... := ... +# 10| 0: [Ident, VariableName] myNested +# 10| Type = func() int +# 10| 1: [FuncLit] function literal +# 10| Type = func() int +# 10| 0: [FuncTypeExpr] function type +# 10| Type = func() int +# 10| 0: [ResultVariableDecl] result variable declaration +# 10| 0: [Ident, TypeName] int +# 10| Type = int +# 10| 1: [BlockStmt] block statement +# 10| 0: [ReturnStmt] return statement +# 10| 0: [IntLit] 1 +# 10| Type = int +# 10| Value = [IntLit] 1 +# 11| 1: [ExprStmt] expression statement +# 11| 0: [CallExpr] call to myNested +# 11| Type = int +# 11| 0: [Ident, VariableName] myNested +# 11| Type = func() int +# 15| 4: [VarDecl] variable declaration +# 15| 0: [ValueSpec] value declaration specifier +# 15| 0: [Ident, VariableName] x +# 15| Type = int +# 15| 1: [Ident, TypeName] int +# 15| Type = int +# 15| 2: [IntLit] 0 +# 15| Type = int +# 15| Value = [IntLit] 0 +# 1| 5: [Ident] main go.mod: # 0| [GoModFile] library-tests/semmle/go/PrintAst/go.mod # 1| 0: [GoModModuleLine] go.mod module line diff --git a/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.ql b/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.ql index 4a36021a31a..4ca15c10ac5 100644 --- a/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.ql +++ b/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.ql @@ -6,7 +6,7 @@ import go import semmle.go.PrintAst class Cfg extends PrintAstConfiguration { - override predicate shouldPrintFunction(FuncDef func) { any() } + override predicate shouldPrintFunction(FuncDecl func) { any() } override predicate shouldPrintFile(File file) { any() } diff --git a/ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.expected b/ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.expected new file mode 100644 index 00000000000..9b1f0da8715 --- /dev/null +++ b/ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.expected @@ -0,0 +1,67 @@ +other.go: +# 0| [File] library-tests/semmle/go/PrintAst/other.go +# 8| 3: [FuncDecl] function declaration +# 8| 0: [FunctionName, Ident] hasNested +# 8| Type = func() +# 8| 1: [FuncTypeExpr] function type +# 8| 2: [BlockStmt] block statement +# 10| 0: [DefineStmt] ... := ... +# 10| 0: [Ident, VariableName] myNested +# 10| Type = func() int +# 10| 1: [FuncLit] function literal +# 10| Type = func() int +# 10| 0: [FuncTypeExpr] function type +# 10| Type = func() int +# 10| 0: [ResultVariableDecl] result variable declaration +# 10| 0: [Ident, TypeName] int +# 10| Type = int +# 10| 1: [BlockStmt] block statement +# 10| 0: [ReturnStmt] return statement +# 10| 0: [IntLit] 1 +# 10| Type = int +# 10| Value = [IntLit] 1 +# 11| 1: [ExprStmt] expression statement +# 11| 0: [CallExpr] call to myNested +# 11| Type = int +# 11| 0: [Ident, VariableName] myNested +# 11| Type = func() int +# 15| 4: [VarDecl] variable declaration +# 15| 0: [ValueSpec] value declaration specifier +# 15| 0: [Ident, VariableName] x +# 15| Type = int +# 15| 1: [Ident, TypeName] int +# 15| Type = int +# 15| 2: [IntLit] 0 +# 15| Type = int +# 15| Value = [IntLit] 0 +# 1| 5: [Ident] main +go.mod: +# 0| [GoModFile] library-tests/semmle/go/PrintAst/go.mod +# 1| 0: [GoModModuleLine] go.mod module line +# 3| 1: [GoModGoLine] go.mod go line +input.go: +# 0| [File] library-tests/semmle/go/PrintAst/input.go +# 5| 0: [CommentGroup] comment group +# 5| 0: [SlashSlashComment] comment +# 7| 1: [CommentGroup] comment group +# 7| 0: [SlashSlashComment] comment +# 9| 2: [DocComment] comment group +# 9| 0: [SlashSlashComment] comment +# 17| 3: [CommentGroup] comment group +# 17| 0: [SlashSlashComment] comment +# 45| 4: [DocComment] comment group +# 45| 0: [SlashSlashComment] comment +# 64| 5: [DocComment] comment group +# 64| 0: [SlashSlashComment] comment +# 74| 6: [DocComment] comment group +# 74| 0: [SlashSlashComment] comment +# 111| 7: [DocComment] comment group +# 111| 0: [SlashSlashComment] comment +# 127| 8: [DocComment] comment group +# 127| 0: [SlashSlashComment] comment +# 132| 9: [DocComment] comment group +# 132| 0: [SlashSlashComment] comment +# 3| 10: [ImportDecl] import declaration +# 3| 0: [ImportSpec] import specifier +# 3| 0: [StringLit] "fmt" +# 1| 18: [Ident] main diff --git a/ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.ql b/ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.ql new file mode 100644 index 00000000000..eaddceacaa3 --- /dev/null +++ b/ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.ql @@ -0,0 +1,14 @@ +/** + * @kind graph + */ + +import go +import semmle.go.PrintAst + +class Cfg extends PrintAstConfiguration { + override predicate shouldPrintFunction(FuncDecl func) { func.getName() = "hasNested" } + + override predicate shouldPrintFile(File file) { any() } + + override predicate shouldPrintComments(File file) { any() } +} diff --git a/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.expected b/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.expected index 20ffb795d94..dbcbcd57826 100644 --- a/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.expected +++ b/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.expected @@ -15,13 +15,38 @@ other.go: # 6| Type = func() # 6| 1: [FuncTypeExpr] function type # 6| 2: [BlockStmt] block statement -# 8| 3: [VarDecl] variable declaration -# 8| 0: [ValueSpec] value declaration specifier -# 8| 0: [Ident, VariableName] x -# 8| Type = int -# 8| 1: [Ident, TypeName] int -# 8| Type = int -# 8| 2: [IntLit] 0 -# 8| Type = int -# 8| Value = [IntLit] 0 -# 1| 4: [Ident] main +# 8| 3: [FuncDecl] function declaration +# 8| 0: [FunctionName, Ident] hasNested +# 8| Type = func() +# 8| 1: [FuncTypeExpr] function type +# 8| 2: [BlockStmt] block statement +# 10| 0: [DefineStmt] ... := ... +# 10| 0: [Ident, VariableName] myNested +# 10| Type = func() int +# 10| 1: [FuncLit] function literal +# 10| Type = func() int +# 10| 0: [FuncTypeExpr] function type +# 10| Type = func() int +# 10| 0: [ResultVariableDecl] result variable declaration +# 10| 0: [Ident, TypeName] int +# 10| Type = int +# 10| 1: [BlockStmt] block statement +# 10| 0: [ReturnStmt] return statement +# 10| 0: [IntLit] 1 +# 10| Type = int +# 10| Value = [IntLit] 1 +# 11| 1: [ExprStmt] expression statement +# 11| 0: [CallExpr] call to myNested +# 11| Type = int +# 11| 0: [Ident, VariableName] myNested +# 11| Type = func() int +# 15| 4: [VarDecl] variable declaration +# 15| 0: [ValueSpec] value declaration specifier +# 15| 0: [Ident, VariableName] x +# 15| Type = int +# 15| 1: [Ident, TypeName] int +# 15| Type = int +# 15| 2: [IntLit] 0 +# 15| Type = int +# 15| Value = [IntLit] 0 +# 1| 5: [Ident] main diff --git a/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.ql b/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.ql index c0c7e57abc6..83d27b9cf26 100644 --- a/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.ql +++ b/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.ql @@ -6,7 +6,7 @@ import go import semmle.go.PrintAst class Cfg extends PrintAstConfiguration { - override predicate shouldPrintFunction(FuncDef func) { any() } + override predicate shouldPrintFunction(FuncDecl func) { any() } override predicate shouldPrintFile(File file) { file.getBaseName() = "other.go" } } diff --git a/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.expected b/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.expected index b64578d6e31..0774687fb4d 100644 --- a/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.expected +++ b/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.expected @@ -5,16 +5,16 @@ other.go: # 6| Type = func() # 6| 1: [FuncTypeExpr] function type # 6| 2: [BlockStmt] block statement -# 8| 3: [VarDecl] variable declaration -# 8| 0: [ValueSpec] value declaration specifier -# 8| 0: [Ident, VariableName] x -# 8| Type = int -# 8| 1: [Ident, TypeName] int -# 8| Type = int -# 8| 2: [IntLit] 0 -# 8| Type = int -# 8| Value = [IntLit] 0 -# 1| 4: [Ident] main +# 15| 4: [VarDecl] variable declaration +# 15| 0: [ValueSpec] value declaration specifier +# 15| 0: [Ident, VariableName] x +# 15| Type = int +# 15| 1: [Ident, TypeName] int +# 15| Type = int +# 15| 2: [IntLit] 0 +# 15| Type = int +# 15| Value = [IntLit] 0 +# 1| 5: [Ident] main go.mod: # 0| [GoModFile] library-tests/semmle/go/PrintAst/go.mod # 1| 0: [GoModModuleLine] go.mod module line diff --git a/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.ql b/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.ql index 83571f02c0d..382fc397755 100644 --- a/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.ql +++ b/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.ql @@ -6,7 +6,7 @@ import go import semmle.go.PrintAst class Cfg extends PrintAstConfiguration { - override predicate shouldPrintFunction(FuncDef func) { func.getName() = "g" } + override predicate shouldPrintFunction(FuncDecl func) { func.getName() = "g" } override predicate shouldPrintFile(File file) { any() } } diff --git a/ql/test/library-tests/semmle/go/PrintAst/other.go b/ql/test/library-tests/semmle/go/PrintAst/other.go index 8a03dea095d..9d60eff98bd 100644 --- a/ql/test/library-tests/semmle/go/PrintAst/other.go +++ b/ql/test/library-tests/semmle/go/PrintAst/other.go @@ -5,4 +5,11 @@ func main() {} func f() {} func g() {} +func hasNested() { + + myNested := func() int { return 1 } + myNested() + +} + var x int = 0