Merge pull request #179 from smowton/smowton/feature/printast

Add barebones PrintAST for Go
This commit is contained in:
Max Schaefer
2020-06-17 17:02:53 +01:00
committed by GitHub
12 changed files with 1273 additions and 9 deletions

View File

@@ -45,6 +45,12 @@ class AstNode extends @node, Locatable {
/** Gets the innermost function definition to which this AST node belongs, if any. */
FuncDef getEnclosingFunction() { result = getParent().parentInSameFunction*() }
/**
* Describes important CodeQL classes for this node. May
* return multiple values.
*/
string describeQlClass() { result = "???" }
override string toString() { result = "AST node" }
}

View File

@@ -27,6 +27,8 @@ class Comment extends @comment, AstNode {
CommentGroup getGroup() { this = result.getAComment() }
override string toString() { result = "comment" }
override string describeQlClass() { result = "Comment" }
}
/**
@@ -59,6 +61,8 @@ class CommentGroup extends @comment_group, AstNode {
int getNumComment() { result = count(getAComment()) }
override string toString() { result = "comment group" }
override string describeQlClass() { result = "CommentGroup" }
}
/**
@@ -109,6 +113,8 @@ class DocComment extends CommentGroup {
/** Gets the program element documented by this comment group. */
Documentable getDocumentedElement() { result = node }
override string describeQlClass() { result = "DocComment" }
}
/**
@@ -120,7 +126,9 @@ class DocComment extends CommentGroup {
* // Single line comment
* ```
*/
class SlashSlashComment extends @slashslashcomment, Comment { }
class SlashSlashComment extends @slashslashcomment, Comment {
override string describeQlClass() { result = "SlashSlashComment" }
}
/**
* A block comment starting with `/*` and ending with <code>*&#47;</code>.
@@ -132,7 +140,9 @@ class SlashSlashComment extends @slashslashcomment, Comment { }
* comment *&#47
* </pre>
*/
class SlashStarComment extends @slashstarcomment, Comment { }
class SlashStarComment extends @slashstarcomment, Comment {
override string describeQlClass() { result = "SlashStarComment" }
}
/**
* A single-line comment starting with `//`.
@@ -194,4 +204,6 @@ class BuildConstraintComment extends LineComment {
// comment text starts with `+build`
getText().regexpMatch("\\s*\\+build.*")
}
override string describeQlClass() { result = "BuildConstraintComment" }
}

View File

@@ -30,6 +30,8 @@ class Decl extends @decl, ExprParent, StmtParent {
*/
class BadDecl extends @baddecl, Decl {
override string toString() { result = "bad declaration" }
override string describeQlClass() { result = "BadDecl" }
}
/**
@@ -46,6 +48,8 @@ class GenDecl extends @gendecl, Decl, Documentable {
int getNumSpec() { result = count(getASpec()) }
override predicate mayHaveSideEffects() { getASpec().mayHaveSideEffects() }
override string describeQlClass() { result = "GenDecl" }
}
/**
@@ -53,6 +57,8 @@ class GenDecl extends @gendecl, Decl, Documentable {
*/
class ImportDecl extends @importdecl, GenDecl {
override string toString() { result = "import declaration" }
override string describeQlClass() { result = "ImportDecl" }
}
/**
@@ -60,6 +66,8 @@ class ImportDecl extends @importdecl, GenDecl {
*/
class ConstDecl extends @constdecl, GenDecl {
override string toString() { result = "constant declaration" }
override string describeQlClass() { result = "ConstDecl" }
}
/**
@@ -67,6 +75,8 @@ class ConstDecl extends @constdecl, GenDecl {
*/
class TypeDecl extends @typedecl, GenDecl {
override string toString() { result = "type declaration" }
override string describeQlClass() { result = "TypeDecl" }
}
/**
@@ -74,6 +84,8 @@ class TypeDecl extends @typedecl, GenDecl {
*/
class VarDecl extends @vardecl, GenDecl {
override string toString() { result = "variable declaration" }
override string describeQlClass() { result = "VarDecl" }
}
/**
@@ -133,6 +145,8 @@ class FuncDef extends @funcdef, StmtParent, ExprParent {
* Gets a call to this function.
*/
DataFlow::CallNode getACall() { result.getACallee() = this }
override string describeQlClass() { result = "FuncDef" }
}
/**
@@ -155,6 +169,8 @@ class FuncDecl extends @funcdecl, Decl, Documentable, FuncDef {
DeclaredFunction getFunction() { this = result.getFuncDecl() }
override string toString() { result = "function declaration" }
override string describeQlClass() { result = "FuncDecl" }
}
/**
@@ -219,6 +235,8 @@ class MethodDecl extends FuncDecl {
* is the variable `p`.
*/
ReceiverVariable getReceiver() { result.getFunction() = this }
override string describeQlClass() { result = "MethodDecl" }
}
/**
@@ -243,6 +261,8 @@ class Spec extends @spec, ExprParent, Documentable {
* Memory allocation is not considered an observable side effect.
*/
predicate mayHaveSideEffects() { none() }
override string describeQlClass() { result = "Spec" }
}
/**
@@ -262,6 +282,8 @@ class ImportSpec extends @importspec, Spec {
string getPath() { result = getPathExpr().getValue() }
override string toString() { result = "import specifier" }
override string describeQlClass() { result = "ImportSpec" }
}
/**
@@ -344,6 +366,8 @@ class ValueSpec extends @valuespec, Spec {
override predicate mayHaveSideEffects() { getAnInit().mayHaveSideEffects() }
override string toString() { result = "value declaration specifier" }
override string describeQlClass() { result = "ValueSpec" }
}
/**
@@ -360,6 +384,8 @@ class TypeSpec extends @typespec, Spec {
Expr getTypeExpr() { result = getChildExpr(1) }
override string toString() { result = "type declaration specifier" }
override string describeQlClass() { result = "TypeSpec" }
}
/**
@@ -397,6 +423,8 @@ class FieldDecl extends @field, Documentable, ExprParent {
StructType getDeclaringType() { result = getDeclaringStructTypeExpr().getType() }
override string toString() { result = "field declaration" }
override string describeQlClass() { result = "FieldDecl" }
}
/**
@@ -404,6 +432,8 @@ class FieldDecl extends @field, Documentable, ExprParent {
*/
class EmbeddedFieldDecl extends FieldDecl {
EmbeddedFieldDecl() { not exists(this.getNameExpr(_)) }
override string describeQlClass() { result = "EmbeddedFieldDecl" }
}
/**
@@ -453,6 +483,8 @@ class ParameterDecl extends @field, Documentable, ExprParent {
}
override string toString() { result = "parameter declaration" }
override string describeQlClass() { result = "ParameterDecl" }
}
/**
@@ -482,6 +514,8 @@ class ReceiverDecl extends @field, Documentable, ExprParent {
Expr getNameExpr() { result = getChildExpr(1) }
override string toString() { result = "receiver declaration" }
override string describeQlClass() { result = "ReceiverDecl" }
}
/**
@@ -531,6 +565,8 @@ class ResultVariableDecl extends @field, Documentable, ExprParent {
int getIndex() { fields(this, _, -(result + 1)) }
override string toString() { result = "result variable declaration" }
override string describeQlClass() { result = "ResultVariableDecl" }
}
/**
@@ -579,6 +615,8 @@ class MethodSpec extends InterfaceMemberSpec {
Expr getNameExpr() { result = name }
override string toString() { result = "method declaration" }
override string describeQlClass() { result = "MethodSpec" }
}
/**
@@ -588,4 +626,6 @@ class EmbeddingSpec extends InterfaceMemberSpec {
EmbeddingSpec() { not exists(getChildExpr(1)) }
override string toString() { result = "interface embedding" }
override string describeQlClass() { result = "EmbeddingSpec" }
}

View File

@@ -155,6 +155,8 @@ class Expr extends @expr, ExprParent {
*/
class BadExpr extends @badexpr, Expr {
override string toString() { result = "bad expression" }
override string describeQlClass() { result = "BadExpr" }
}
/**
@@ -180,6 +182,8 @@ class Ident extends @ident, Expr {
predicate refersTo(Entity e) { uses(e) or declares(e) }
override string toString() { result = getName() }
override string describeQlClass() { result = "Ident" }
}
/**
@@ -193,6 +197,8 @@ class Ident extends @ident, Expr {
*/
class BlankIdent extends Ident {
BlankIdent() { getName() = "_" }
override string describeQlClass() { result = "BlankIdent" }
}
/**
@@ -210,6 +216,8 @@ class Ellipsis extends @ellipsis, Expr {
Expr getOperand() { result = getChildExpr(0) }
override string toString() { result = "..." }
override string describeQlClass() { result = "Ellipsis" }
}
/**
@@ -267,7 +275,9 @@ class BasicLit extends @basiclit, Literal {
* 256
* ```
*/
class IntLit extends @intlit, BasicLit { }
class IntLit extends @intlit, BasicLit {
override string describeQlClass() { result = "IntLit" }
}
/**
* A floating-point literal.
@@ -278,7 +288,9 @@ class IntLit extends @intlit, BasicLit { }
* 2.71828
* ```
*/
class FloatLit extends @floatlit, BasicLit { }
class FloatLit extends @floatlit, BasicLit {
override string describeQlClass() { result = "FloatLit" }
}
/**
* An imaginary literal.
@@ -290,7 +302,9 @@ class FloatLit extends @floatlit, BasicLit { }
* 2.7i
* ```
*/
class ImagLit extends @imaglit, BasicLit { }
class ImagLit extends @imaglit, BasicLit {
override string describeQlClass() { result = "ImagLit" }
}
/**
* A rune literal.
@@ -312,6 +326,8 @@ class CharLit extends @charlit, BasicLit {
// use the constant value of the literal as the string value, as the value we get from the
// compiler is an integer, meaning we would not otherwise have a string value for rune literals
override string getStringValue() { result = this.getValue() }
override string describeQlClass() { result = "CharLit" }
}
class RuneLit = CharLit;
@@ -325,7 +341,9 @@ class RuneLit = CharLit;
* "hello world"
* ```
*/
class StringLit extends @stringlit, BasicLit { }
class StringLit extends @stringlit, BasicLit {
override string describeQlClass() { result = "StringLit" }
}
/**
* A function literal.
@@ -347,6 +365,8 @@ class FuncLit extends @funclit, Literal, StmtParent, FuncDef {
override predicate isPlatformIndependentConstant() { any() }
override string toString() { result = "function literal" }
override string describeQlClass() { result = "FuncLit" }
}
/**
@@ -394,6 +414,8 @@ class CompositeLit extends @compositelit, Literal {
}
override string toString() { result = "composite literal" }
override string describeQlClass() { result = "CompositeLit" }
}
/**
@@ -417,6 +439,8 @@ class MapLit extends CompositeLit {
Type getValueType() { result = mt.getValueType() }
override string toString() { result = "map literal" }
override string describeQlClass() { result = "MapLit" }
}
/**
@@ -439,6 +463,8 @@ class StructLit extends CompositeLit {
StructType getStructType() { result = st }
override string toString() { result = "struct literal" }
override string describeQlClass() { result = "StructLit" }
}
/**
@@ -485,6 +511,8 @@ class ArrayLit extends ArrayOrSliceLit {
ArrayType getArrayType() { result = type }
override string toString() { result = "array literal" }
override string describeQlClass() { result = "ArrayLit" }
}
/**
@@ -504,6 +532,8 @@ class SliceLit extends ArrayOrSliceLit {
SliceType getSliceType() { result = type }
override string toString() { result = "slice literal" }
override string describeQlClass() { result = "SliceLit" }
}
/**
@@ -524,6 +554,8 @@ class ParenExpr extends @parenexpr, Expr {
override predicate isPlatformIndependentConstant() { getExpr().isPlatformIndependentConstant() }
override string toString() { result = "(...)" }
override string describeQlClass() { result = "ParenExpr" }
}
/**
@@ -554,6 +586,8 @@ class SelectorExpr extends @selectorexpr, Expr {
override predicate mayHaveOwnSideEffects() { any() }
override string toString() { result = "selection of " + getSelector() }
override string describeQlClass() { result = "SelectorExpr" }
}
/**
@@ -575,6 +609,8 @@ class IndexExpr extends @indexexpr, Expr {
override predicate mayHaveOwnSideEffects() { any() }
override string toString() { result = "index expression" }
override string describeQlClass() { result = "IndexExpr" }
}
/**
@@ -601,6 +637,8 @@ class SliceExpr extends @sliceexpr, Expr {
Expr getMax() { result = getChildExpr(3) }
override string toString() { result = "slice expression" }
override string describeQlClass() { result = "SliceExpr" }
}
/**
@@ -624,6 +662,8 @@ class TypeAssertExpr extends @typeassertexpr, Expr {
override predicate isPlatformIndependentConstant() { getExpr().isPlatformIndependentConstant() }
override string toString() { result = "type assertion" }
override string describeQlClass() { result = "TypeAssertExpr" }
}
/**
@@ -641,7 +681,9 @@ class TypeAssertExpr extends @typeassertexpr, Expr {
* []byte("x")
* ```
*/
class CallOrConversionExpr extends @callorconversionexpr, Expr { }
class CallOrConversionExpr extends @callorconversionexpr, Expr {
override string describeQlClass() { result = "CallOrConversionExpr" }
}
/**
* A type conversion expression.
@@ -666,6 +708,8 @@ class ConversionExpr extends CallOrConversionExpr {
}
override string toString() { result = "type conversion" }
override string describeQlClass() { result = "ConversionExpr" }
}
/**
@@ -722,6 +766,8 @@ class CallExpr extends CallOrConversionExpr {
not exists(getCalleeName()) and
result = "function call"
}
override string describeQlClass() { result = "CallExpr" }
}
/**
@@ -740,6 +786,8 @@ class StarExpr extends @starexpr, Expr {
override predicate mayHaveOwnSideEffects() { any() }
override string toString() { result = "star expression" }
override string describeQlClass() { result = "StarExpr" }
}
/**
@@ -762,6 +810,8 @@ class KeyValueExpr extends @keyvalueexpr, Expr {
CompositeLit getLiteral() { this = result.getElement(_) }
override string toString() { result = "key-value pair" }
override string describeQlClass() { result = "KeyValueExpr" }
}
/**
@@ -781,6 +831,8 @@ class ArrayTypeExpr extends @arraytypeexpr, TypeExpr {
Expr getElement() { result = getChildExpr(1) }
override string toString() { result = "array type" }
override string describeQlClass() { result = "ArrayTypeExpr" }
}
/**
@@ -803,6 +855,8 @@ class StructTypeExpr extends @structtypeexpr, TypeExpr {
int getNumField() { result = count(getAField()) }
override string toString() { result = "struct type" }
override string describeQlClass() { result = "StructTypeExpr" }
}
/**
@@ -843,6 +897,8 @@ class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode {
ResultVariableDecl getResultDecl() { getNumResult() = 1 and result = getAResultDecl() }
override string toString() { result = "function type" }
override string describeQlClass() { result = "FuncTypeExpr" }
}
/**
@@ -868,6 +924,8 @@ class InterfaceTypeExpr extends @interfacetypeexpr, TypeExpr {
int getNumMethod() { result = count(getAMethod()) }
override string toString() { result = "interface type" }
override string describeQlClass() { result = "InterfaceTypeExpr" }
}
/**
@@ -893,6 +951,8 @@ class MapTypeExpr extends @maptypeexpr, TypeExpr {
Type getValueType() { result = getValueTypeExpr().getType() }
override string toString() { result = "map type" }
override string describeQlClass() { result = "MapTypeExpr" }
}
/**
@@ -1018,6 +1078,8 @@ class BitwiseUnaryExpr extends @bitwiseunaryexpr, BitwiseExpr, UnaryExpr { }
*/
class PlusExpr extends @plusexpr, ArithmeticUnaryExpr {
override string getOperator() { result = "+" }
override string describeQlClass() { result = "PlusExpr" }
}
/**
@@ -1031,6 +1093,8 @@ class PlusExpr extends @plusexpr, ArithmeticUnaryExpr {
*/
class MinusExpr extends @minusexpr, ArithmeticUnaryExpr {
override string getOperator() { result = "-" }
override string describeQlClass() { result = "MinusExpr" }
}
/**
@@ -1044,6 +1108,8 @@ class MinusExpr extends @minusexpr, ArithmeticUnaryExpr {
*/
class NotExpr extends @notexpr, LogicalUnaryExpr {
override string getOperator() { result = "!" }
override string describeQlClass() { result = "NotExpr" }
}
/**
@@ -1057,6 +1123,8 @@ class NotExpr extends @notexpr, LogicalUnaryExpr {
*/
class ComplementExpr extends @complementexpr, BitwiseUnaryExpr {
override string getOperator() { result = "^" }
override string describeQlClass() { result = "ComplementExpr" }
}
/**
@@ -1068,6 +1136,8 @@ class DerefExpr extends @derefexpr, UnaryExpr {
override predicate mayHaveOwnSideEffects() { any() }
override string getOperator() { result = "*" }
override string describeQlClass() { result = "DerefExpr" }
}
/**
@@ -1083,6 +1153,8 @@ class AddressExpr extends @addressexpr, UnaryExpr {
override predicate mayHaveOwnSideEffects() { any() }
override string getOperator() { result = "&" }
override string describeQlClass() { result = "AddressExpr" }
}
/**
@@ -1098,6 +1170,8 @@ class RecvExpr extends @arrowexpr, UnaryExpr {
override predicate mayHaveOwnSideEffects() { any() }
override string getOperator() { result = "<-" }
override string describeQlClass() { result = "RecvExpr" }
}
/**
@@ -1243,6 +1317,8 @@ class RelationalComparisonExpr extends @relationalcomparison, ComparisonExpr {
*/
class LorExpr extends @lorexpr, LogicalBinaryExpr {
override string getOperator() { result = "||" }
override string describeQlClass() { result = "LorExpr" }
}
class LogOrExpr = LorExpr;
@@ -1258,6 +1334,8 @@ class LogOrExpr = LorExpr;
*/
class LandExpr extends @landexpr, LogicalBinaryExpr {
override string getOperator() { result = "&&" }
override string describeQlClass() { result = "LandExpr" }
}
class LogAndExpr = LandExpr;
@@ -1275,6 +1353,8 @@ class EqlExpr extends @eqlexpr, EqualityTestExpr {
override string getOperator() { result = "==" }
override boolean getPolarity() { result = true }
override string describeQlClass() { result = "EqlExpr" }
}
class EqExpr = EqlExpr;
@@ -1292,6 +1372,8 @@ class NeqExpr extends @neqexpr, EqualityTestExpr {
override string getOperator() { result = "!=" }
override boolean getPolarity() { result = false }
override string describeQlClass() { result = "NeqExpr" }
}
/**
@@ -1311,6 +1393,8 @@ class LssExpr extends @lssexpr, RelationalComparisonExpr {
override Expr getLesserOperand() { result = getLeftOperand() }
override Expr getGreaterOperand() { result = getRightOperand() }
override string describeQlClass() { result = "LssExpr" }
}
class LTExpr = LssExpr;
@@ -1330,6 +1414,8 @@ class LeqExpr extends @leqexpr, RelationalComparisonExpr {
override Expr getLesserOperand() { result = getLeftOperand() }
override Expr getGreaterOperand() { result = getRightOperand() }
override string describeQlClass() { result = "LeqExpr" }
}
class LEExpr = LeqExpr;
@@ -1351,6 +1437,8 @@ class GtrExpr extends @gtrexpr, RelationalComparisonExpr {
override Expr getLesserOperand() { result = getRightOperand() }
override Expr getGreaterOperand() { result = getLeftOperand() }
override string describeQlClass() { result = "GtrExpr" }
}
class GTExpr = GtrExpr;
@@ -1370,6 +1458,8 @@ class GeqExpr extends @geqexpr, RelationalComparisonExpr {
override Expr getLesserOperand() { result = getRightOperand() }
override Expr getGreaterOperand() { result = getLeftOperand() }
override string describeQlClass() { result = "GeqExpr" }
}
class GEExpr = GeqExpr;
@@ -1385,6 +1475,8 @@ class GEExpr = GeqExpr;
*/
class AddExpr extends @addexpr, ArithmeticBinaryExpr {
override string getOperator() { result = "+" }
override string describeQlClass() { result = "AddExpr" }
}
/**
@@ -1398,6 +1490,8 @@ class AddExpr extends @addexpr, ArithmeticBinaryExpr {
*/
class SubExpr extends @subexpr, ArithmeticBinaryExpr {
override string getOperator() { result = "-" }
override string describeQlClass() { result = "SubExpr" }
}
/**
@@ -1411,6 +1505,8 @@ class SubExpr extends @subexpr, ArithmeticBinaryExpr {
*/
class OrExpr extends @orexpr, BitwiseBinaryExpr {
override string getOperator() { result = "|" }
override string describeQlClass() { result = "OrExpr" }
}
class BitOrExpr = OrExpr;
@@ -1426,6 +1522,8 @@ class BitOrExpr = OrExpr;
*/
class XorExpr extends @xorexpr, BitwiseBinaryExpr {
override string getOperator() { result = "^" }
override string describeQlClass() { result = "XorExpr" }
}
/**
@@ -1439,6 +1537,8 @@ class XorExpr extends @xorexpr, BitwiseBinaryExpr {
*/
class MulExpr extends @mulexpr, ArithmeticBinaryExpr {
override string getOperator() { result = "*" }
override string describeQlClass() { result = "MulExpr" }
}
/**
@@ -1454,6 +1554,8 @@ class QuoExpr extends @quoexpr, ArithmeticBinaryExpr {
override predicate mayHaveOwnSideEffects() { any() }
override string getOperator() { result = "/" }
override string describeQlClass() { result = "QuoExpr" }
}
class DivExpr = QuoExpr;
@@ -1469,6 +1571,8 @@ class DivExpr = QuoExpr;
*/
class RemExpr extends @remexpr, ArithmeticBinaryExpr {
override string getOperator() { result = "%" }
override string describeQlClass() { result = "RemExpr" }
}
class ModExpr = RemExpr;
@@ -1484,6 +1588,8 @@ class ModExpr = RemExpr;
*/
class ShlExpr extends @shlexpr, ShiftExpr {
override string getOperator() { result = "<<" }
override string describeQlClass() { result = "ShlExpr" }
}
class LShiftExpr = ShlExpr;
@@ -1499,6 +1605,8 @@ class LShiftExpr = ShlExpr;
*/
class ShrExpr extends @shrexpr, ShiftExpr {
override string getOperator() { result = ">>" }
override string describeQlClass() { result = "ShrExpr" }
}
class RShiftExpr = ShrExpr;
@@ -1514,6 +1622,8 @@ class RShiftExpr = ShrExpr;
*/
class AndExpr extends @andexpr, BitwiseBinaryExpr {
override string getOperator() { result = "&" }
override string describeQlClass() { result = "AndExpr" }
}
class BitAndExpr = AndExpr;
@@ -1529,6 +1639,8 @@ class BitAndExpr = AndExpr;
*/
class AndNotExpr extends @andnotexpr, BitwiseBinaryExpr {
override string getOperator() { result = "&^" }
override string describeQlClass() { result = "AndNotExpr" }
}
/**
@@ -1555,6 +1667,8 @@ class ChanTypeExpr extends @chantypeexpr, TypeExpr {
predicate canReceive() { none() }
override string toString() { result = "channel type" }
override string describeQlClass() { result = "ChanTypeExpr" }
}
/**
@@ -1568,6 +1682,8 @@ class ChanTypeExpr extends @chantypeexpr, TypeExpr {
*/
class SendChanTypeExpr extends @sendchantypeexpr, ChanTypeExpr {
override predicate canSend() { any() }
override string describeQlClass() { result = "SendChanTypeExpr" }
}
/**
@@ -1581,6 +1697,8 @@ class SendChanTypeExpr extends @sendchantypeexpr, ChanTypeExpr {
*/
class RecvChanTypeExpr extends @recvchantypeexpr, ChanTypeExpr {
override predicate canReceive() { any() }
override string describeQlClass() { result = "RecvChanTypeExpr" }
}
/**
@@ -1596,6 +1714,8 @@ class SendRecvChanTypeExpr extends @sendrcvchantypeexpr, ChanTypeExpr {
override predicate canSend() { any() }
override predicate canReceive() { any() }
override string describeQlClass() { result = "SendRecvChanTypeExpr" }
}
/**
@@ -1658,6 +1778,8 @@ class PackageName extends Name {
/** Gets the package this name refers to. */
override PackageEntity getTarget() { result = target }
override string describeQlClass() { result = "PackageName" }
}
/**
@@ -1675,6 +1797,8 @@ class TypeName extends Name {
/** Gets the type this name refers to. */
override TypeEntity getTarget() { result = target }
override string describeQlClass() { result = "TypeName" }
}
/**
@@ -1693,6 +1817,8 @@ class ValueName extends Name {
/** Gets the constant, variable or function this name refers to. */
override ValueEntity getTarget() { result = target }
override string describeQlClass() { result = "ValueName" }
}
/**
@@ -1722,6 +1848,8 @@ class ConstantName extends ValueName {
c.getInit().isPlatformIndependentConstant()
)
}
override string describeQlClass() { result = "ConstantName" }
}
/**
@@ -1738,6 +1866,8 @@ class VariableName extends ValueName {
/** Gets the variable this name refers to. */
override Variable getTarget() { result = target }
override string describeQlClass() { result = "VariableName" }
}
/**
@@ -1754,6 +1884,8 @@ class FunctionName extends ValueName {
/** Gets the function this name refers to. */
override Function getTarget() { result = target }
override string describeQlClass() { result = "FunctionName" }
}
/**
@@ -1770,6 +1902,8 @@ class LabelName extends Name {
/** Gets the label this name refers to. */
override Label getTarget() { result = target }
override string describeQlClass() { result = "LabelName" }
}
/**

View File

@@ -207,4 +207,6 @@ class File extends Container, @file, Documentable, ExprParent, GoModExprParent,
/** Gets the URL of this file. */
override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" }
override string describeQlClass() { result = "File" }
}

View File

@@ -12,6 +12,8 @@ class GoModFile extends File {
* Gets the module declaration of this file, that is, the line declaring the path of this module.
*/
GoModModuleLine getModuleDeclaration() { result.getFile() = this }
override string describeQlClass() { result = "GoModFile" }
}
/**
@@ -38,12 +40,16 @@ class GoModExpr extends @modexpr, GoModExprParent {
string getModulePath() { result = this.getFile().getModuleDeclaration().getPath() }
override string toString() { result = "go.mod expression" }
override string describeQlClass() { result = "GoModExpr" }
}
/**
* A top-level block of comments separate from any rule.
*/
class GoModCommentBlock extends @modcommentblock, GoModExpr { }
class GoModCommentBlock extends @modcommentblock, GoModExpr {
override string describeQlClass() { result = "GoModCommentBlock" }
}
/**
* A single line of tokens.
@@ -86,6 +92,8 @@ class GoModLine extends @modline, GoModExpr {
}
override string toString() { result = "go.mod line" }
override string describeQlClass() { result = "GoModLine" }
}
/**
@@ -107,6 +115,8 @@ class GoModLineBlock extends @modlineblock, GoModExpr {
string getRawToken(int i) { modtokens(result, this, i) }
override string toString() { result = "go.mod line block" }
override string describeQlClass() { result = "GoModLineBlock" }
}
/**
@@ -121,6 +131,8 @@ class GoModModuleLine extends GoModLine {
string getPath() { result = this.getToken(1) }
override string toString() { result = "go.mod module line" }
override string describeQlClass() { result = "GoModModuleLine" }
}
/**
@@ -133,6 +145,8 @@ class GoModGoLine extends GoModLine {
string getVersion() { result = this.getToken(1) }
override string toString() { result = "go.mod go line" }
override string describeQlClass() { result = "GoModGoLine" }
}
/**
@@ -148,6 +162,8 @@ class GoModRequireLine extends GoModLine {
string getVersion() { result = this.getToken(2) }
override string toString() { result = "go.mod require line" }
override string describeQlClass() { result = "GoModRequireLine" }
}
/**
@@ -164,6 +180,8 @@ class GoModExcludeLine extends GoModLine {
string getVersion() { result = this.getToken(2) }
override string toString() { result = "go.mod exclude line" }
override string describeQlClass() { result = "GoModExcludeLine" }
}
/**
@@ -194,14 +212,20 @@ class GoModReplaceLine extends GoModLine {
}
override string toString() { result = "go.mod replace line" }
override string describeQlClass() { result = "GoModReplaceLine" }
}
/** A left parenthesis for a line block. */
class GoModLParen extends @modlparen, GoModExpr {
override string toString() { result = "go.mod (" }
override string describeQlClass() { result = "GoModLParen" }
}
/** A right parenthesis for a line block. */
class GoModRParen extends @modrparen, GoModExpr {
override string toString() { result = "go.mod )" }
override string describeQlClass() { result = "GoModRParen" }
}

View File

@@ -0,0 +1,16 @@
/**
* @name Print AST
* @description Outputs a representation of the Abstract Syntax Tree.
* @id go/print-ast
* @kind graph
*/
import go
import PrintAst
/**
* Hook to customize the functions printed by this query.
*/
class Cfg extends PrintAstConfiguration {
override predicate shouldPrintFunction(FuncDef func) { any() }
}

View File

@@ -0,0 +1,209 @@
/**
* Provides queries to pretty-print a Go AST as a graph.
*/
import go
/**
* Hook to customize the functions printed by this module.
*/
class PrintAstConfiguration extends string {
/**
* Restrict to a single string, making this a singleton type.
*/
PrintAstConfiguration() { this = "PrintAstConfiguration" }
/**
* Holds if the AST for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(FuncDef func) { any() }
}
private predicate shouldPrintFunction(FuncDef func) {
exists(PrintAstConfiguration config | config.shouldPrintFunction(func))
}
/**
* An AST node that should be printed.
*/
private newtype TPrintAstNode =
TAstNode(AstNode ast) {
// Do print ast nodes without an enclosing function, e.g. file headers
forall(FuncDef f | f = ast.getEnclosingFunction() | shouldPrintFunction(f))
}
/**
* A node in the output tree.
*/
class PrintAstNode extends TPrintAstNode {
/**
* Gets a textual representation of this node.
*/
abstract string toString();
/**
* Gets the child node at index `childIndex`. Child indices must be unique,
* but need not be contiguous.
*/
abstract PrintAstNode getChild(int childIndex);
/**
* Holds if this node should be printed in the output. By default, all nodes
* within a function are printed, but the query can override
* `PrintAstConfiguration.shouldPrintFunction` to filter the output.
*/
predicate shouldPrint() { exists(getLocation()) }
/**
* Gets a child of this node.
*/
PrintAstNode getAChild() { result = getChild(_) }
/**
* Gets the location of this node in the source code.
*/
abstract Location getLocation();
/**
* Gets the value of the property of this node, where the name of the property
* is `key`.
*/
string getProperty(string key) {
key = "semmle.label" and
result = toString()
}
/**
* Gets the label for the edge from this node to the specified child. By
* default, this is just the index of the child, but subclasses can override
* this.
*/
string getChildEdgeLabel(int childIndex) {
exists(getChild(childIndex)) and
result = childIndex.toString()
}
/**
* Gets the `FuncDef` that contains this node.
*/
abstract FuncDef getEnclosingFunction();
}
/**
* Gets a pretty-printed representation of the QL class(es) for entity `el`.
*/
private string qlClass(AstNode el) {
// This version shows all non-overridden QL classes:
// result = "[" + concat(el.getAQlClass(), ", ") + "] "
// Normally we prefer to show just the canonical class:
result = "[" + concat(el.describeQlClass(), ", ") + "] "
}
/**
* Gets a child with the given index and of the given kind, if one exists.
* Note that a given parent can have multiple children with the same index but differing kind.
*/
private AstNode getChildOfKind(AstNode parent, string kind, int i) {
kind = "expr" and result = parent.(ExprParent).getChildExpr(i)
or
kind = "gomodexpr" and result = parent.(GoModExprParent).getChildGoModExpr(i)
or
kind = "stmt" and result = parent.(StmtParent).getChildStmt(i)
or
kind = "decl" and result = parent.(DeclParent).getDecl(i)
or
kind = "spec" and result = parent.(GenDecl).getSpec(i)
or
kind = "field" and fields(result, parent, i)
}
/**
* Get an AstNode child, ordered by child kind and then by index
*/
private AstNode getUniquelyNumberedChild(AstNode node, int index) {
result =
rank[index + 1](AstNode child, string kind, int i |
child = getChildOfKind(node, kind, i)
|
child order by kind, i
)
}
/**
* A graph node representing a real AST node.
*/
class BaseAstNode extends PrintAstNode, TAstNode {
AstNode ast;
BaseAstNode() { this = TAstNode(ast) }
override BaseAstNode getChild(int childIndex) {
// Note a node can have several results for getChild(n) because some
// nodes have multiple different types of child (e.g. a File has a
// child expression, the package name, and child declarations whose
// indices may clash), so we renumber them:
result = TAstNode(getUniquelyNumberedChild(ast, childIndex))
}
override string toString() { result = qlClass(ast) + ast }
final override Location getLocation() { result = ast.getLocation() }
final override FuncDef getEnclosingFunction() {
result = ast or result = ast.getEnclosingFunction()
}
}
/**
* A node representing an `Expr`.
*/
class ExprNode extends BaseAstNode {
override Expr ast;
override string getProperty(string key) {
result = super.getProperty(key)
or
key = "Value" and
result = qlClass(ast) + ast.getExactValue()
or
key = "Type" and
not ast.getType() instanceof InvalidType and
result = ast.getType().pp()
}
}
/**
* A node representing a `File`
*/
class FileNode extends BaseAstNode {
override File ast;
/**
* Gets the string representation of this File. Note explicitly using a relative path
* like this rather than absolute as per default for the File class is a workaround for
* a bug with codeql run test, which should replace absolute paths but currently does not.
*/
override string toString() { result = qlClass(ast) + ast.getRelativePath() }
}
query predicate nodes(PrintAstNode node, string key, string value) {
node.shouldPrint() and
value = node.getProperty(key)
}
query predicate edges(PrintAstNode source, PrintAstNode target, string key, string value) {
exists(int childIndex |
source.shouldPrint() and
target.shouldPrint() and
target = source.getChild(childIndex)
|
key = "semmle.label" and value = source.getChildEdgeLabel(childIndex)
or
key = "semmle.order" and value = childIndex.toString()
)
}
query predicate graphProperties(string key, string value) {
key = "semmle.graphKind" and value = "tree"
}

View File

@@ -52,6 +52,8 @@ class Stmt extends @stmt, ExprParent, StmtParent {
*/
class BadStmt extends @badstmt, Stmt {
override string toString() { result = "bad statement" }
override string describeQlClass() { result = "BadStmt" }
}
/**
@@ -72,6 +74,8 @@ class DeclStmt extends @declstmt, Stmt, DeclParent {
override predicate mayHaveSideEffects() { getDecl().mayHaveSideEffects() }
override string toString() { result = "declaration statement" }
override string describeQlClass() { result = "DeclStmt" }
}
/**
@@ -85,6 +89,8 @@ class DeclStmt extends @declstmt, Stmt, DeclParent {
*/
class EmptyStmt extends @emptystmt, Stmt {
override string toString() { result = "empty statement" }
override string describeQlClass() { result = "EmptyStmt" }
}
/**
@@ -109,6 +115,8 @@ class LabeledStmt extends @labeledstmt, Stmt {
override predicate mayHaveSideEffects() { getStmt().mayHaveSideEffects() }
override string toString() { result = "labeled statement" }
override string describeQlClass() { result = "LabelledStmt" }
}
/**
@@ -130,6 +138,8 @@ class ExprStmt extends @exprstmt, Stmt {
override predicate mayHaveSideEffects() { getExpr().mayHaveSideEffects() }
override string toString() { result = "expression statement" }
override string describeQlClass() { result = "ExprStmt" }
}
/**
@@ -151,6 +161,8 @@ class SendStmt extends @sendstmt, Stmt {
override predicate mayHaveSideEffects() { any() }
override string toString() { result = "send statement" }
override string describeQlClass() { result = "SendStmt" }
}
/**
@@ -186,6 +198,8 @@ class IncStmt extends @incstmt, IncDecStmt {
override string getOperator() { result = "++" }
override string toString() { result = "increment statement" }
override string describeQlClass() { result = "IncStmt" }
}
/**
@@ -201,6 +215,8 @@ class DecStmt extends @decstmt, IncDecStmt {
override string getOperator() { result = "--" }
override string toString() { result = "decrement statement" }
override string describeQlClass() { result = "DecStmt" }
}
/**
@@ -270,7 +286,9 @@ class Assignment extends @assignment, Stmt {
* (k) = <-ch // same as: k = <-ch
* ```
*/
class SimpleAssignStmt extends @simpleassignstmt, Assignment { }
class SimpleAssignStmt extends @simpleassignstmt, Assignment {
override string describeQlClass() { result = "SimpleAssignStmt" }
}
/**
* A plain assignment statement.
@@ -285,6 +303,8 @@ class SimpleAssignStmt extends @simpleassignstmt, Assignment { }
*/
class AssignStmt extends @assignstmt, SimpleAssignStmt {
override string getOperator() { result = "=" }
override string describeQlClass() { result = "AssignStmt" }
}
/**
@@ -298,6 +318,8 @@ class AssignStmt extends @assignstmt, SimpleAssignStmt {
*/
class DefineStmt extends @definestmt, SimpleAssignStmt {
override string getOperator() { result = ":=" }
override string describeQlClass() { result = "DefineStmt" }
}
/**
@@ -323,6 +345,8 @@ class CompoundAssignStmt extends @compoundassignstmt, Assignment { }
*/
class AddAssignStmt extends @addassignstmt, CompoundAssignStmt {
override string getOperator() { result = "+=" }
override string describeQlClass() { result = "AddAssignStmt" }
}
/**
@@ -336,6 +360,8 @@ class AddAssignStmt extends @addassignstmt, CompoundAssignStmt {
*/
class SubAssignStmt extends @subassignstmt, CompoundAssignStmt {
override string getOperator() { result = "-=" }
override string describeQlClass() { result = "SubAssignStmt" }
}
/**
@@ -349,6 +375,8 @@ class SubAssignStmt extends @subassignstmt, CompoundAssignStmt {
*/
class MulAssignStmt extends @mulassignstmt, CompoundAssignStmt {
override string getOperator() { result = "*=" }
override string describeQlClass() { result = "MulAssignStmt" }
}
/**
@@ -362,6 +390,8 @@ class MulAssignStmt extends @mulassignstmt, CompoundAssignStmt {
*/
class QuoAssignStmt extends @quoassignstmt, CompoundAssignStmt {
override string getOperator() { result = "/=" }
override string describeQlClass() { result = "QuoAssignStmt" }
}
class DivAssignStmt = QuoAssignStmt;
@@ -377,6 +407,8 @@ class DivAssignStmt = QuoAssignStmt;
*/
class RemAssignStmt extends @remassignstmt, CompoundAssignStmt {
override string getOperator() { result = "%=" }
override string describeQlClass() { result = "RemAssignStmt" }
}
class ModAssignStmt = RemAssignStmt;
@@ -392,6 +424,8 @@ class ModAssignStmt = RemAssignStmt;
*/
class AndAssignStmt extends @andassignstmt, CompoundAssignStmt {
override string getOperator() { result = "&=" }
override string describeQlClass() { result = "AndAssignStmt" }
}
/**
@@ -405,6 +439,8 @@ class AndAssignStmt extends @andassignstmt, CompoundAssignStmt {
*/
class OrAssignStmt extends @orassignstmt, CompoundAssignStmt {
override string getOperator() { result = "|=" }
override string describeQlClass() { result = "OrAssignStmt" }
}
/**
@@ -418,6 +454,8 @@ class OrAssignStmt extends @orassignstmt, CompoundAssignStmt {
*/
class XorAssignStmt extends @xorassignstmt, CompoundAssignStmt {
override string getOperator() { result = "^=" }
override string describeQlClass() { result = "XorAssignStmt" }
}
/**
@@ -431,6 +469,8 @@ class XorAssignStmt extends @xorassignstmt, CompoundAssignStmt {
*/
class ShlAssignStmt extends @shlassignstmt, CompoundAssignStmt {
override string getOperator() { result = "<<=" }
override string describeQlClass() { result = "ShlAssignStmt" }
}
class LShiftAssignStmt = ShlAssignStmt;
@@ -446,6 +486,8 @@ class LShiftAssignStmt = ShlAssignStmt;
*/
class ShrAssignStmt extends @shrassignstmt, CompoundAssignStmt {
override string getOperator() { result = ">>=" }
override string describeQlClass() { result = "ShrAssignStmt" }
}
class RShiftAssignStmt = ShrAssignStmt;
@@ -461,6 +503,8 @@ class RShiftAssignStmt = ShrAssignStmt;
*/
class AndNotAssignStmt extends @andnotassignstmt, CompoundAssignStmt {
override string getOperator() { result = "&^=" }
override string describeQlClass() { result = "AndNotAssignStmt" }
}
/**
@@ -479,6 +523,8 @@ class GoStmt extends @gostmt, Stmt {
override predicate mayHaveSideEffects() { getCall().mayHaveSideEffects() }
override string toString() { result = "go statement" }
override string describeQlClass() { result = "GoStmt" }
}
/**
@@ -497,6 +543,8 @@ class DeferStmt extends @deferstmt, Stmt {
override predicate mayHaveSideEffects() { getCall().mayHaveSideEffects() }
override string toString() { result = "defer statement" }
override string describeQlClass() { result = "DeferStmt" }
}
/**
@@ -524,6 +572,8 @@ class ReturnStmt extends @returnstmt, Stmt {
override predicate mayHaveSideEffects() { getExpr().mayHaveSideEffects() }
override string toString() { result = "return statement" }
override string describeQlClass() { result = "ReturnStmt" }
}
/**
@@ -560,6 +610,8 @@ class BranchStmt extends @branchstmt, Stmt {
*/
class BreakStmt extends @breakstmt, BranchStmt {
override string toString() { result = "break statement" }
override string describeQlClass() { result = "BreakStmt" }
}
/**
@@ -574,6 +626,8 @@ class BreakStmt extends @breakstmt, BranchStmt {
*/
class ContinueStmt extends @continuestmt, BranchStmt {
override string toString() { result = "continue statement" }
override string describeQlClass() { result = "ContinueStmt" }
}
/**
@@ -587,6 +641,8 @@ class ContinueStmt extends @continuestmt, BranchStmt {
*/
class GotoStmt extends @gotostmt, BranchStmt {
override string toString() { result = "goto statement" }
override string describeQlClass() { result = "GotoStmt" }
}
/**
@@ -600,6 +656,8 @@ class GotoStmt extends @gotostmt, BranchStmt {
*/
class FallthroughStmt extends @fallthroughstmt, BranchStmt {
override string toString() { result = "fallthrough statement" }
override string describeQlClass() { result = "FallthroughStmt" }
}
/**
@@ -627,6 +685,8 @@ class BlockStmt extends @blockstmt, Stmt, ScopeNode {
override predicate mayHaveSideEffects() { getAStmt().mayHaveSideEffects() }
override string toString() { result = "block statement" }
override string describeQlClass() { result = "BlockStmt" }
}
/**
@@ -663,6 +723,8 @@ class IfStmt extends @ifstmt, Stmt, ScopeNode {
}
override string toString() { result = "if statement" }
override string describeQlClass() { result = "IfStmt" }
}
/**
@@ -707,6 +769,8 @@ class CaseClause extends @caseclause, Stmt, ScopeNode {
}
override string toString() { result = "case clause" }
override string describeQlClass() { result = "CaseClause" }
}
/**
@@ -792,6 +856,8 @@ class ExpressionSwitchStmt extends @exprswitchstmt, SwitchStmt {
}
override string toString() { result = "expression-switch statement" }
override string describeQlClass() { result = "ExpressionSwitchStmt" }
}
/**
@@ -822,6 +888,8 @@ class TypeSwitchStmt extends @typeswitchstmt, SwitchStmt {
override predicate mayHaveSideEffects() { any() }
override string toString() { result = "type-switch statement" }
override string describeQlClass() { result = "TypeSwitchStmt" }
}
/**
@@ -863,6 +931,8 @@ class CommClause extends @commclause, Stmt, ScopeNode {
override predicate mayHaveSideEffects() { getAStmt().mayHaveSideEffects() }
override string toString() { result = "comm clause" }
override string describeQlClass() { result = "CommClause" }
}
/**
@@ -890,6 +960,8 @@ class RecvStmt extends Stmt {
result = this.(ExprStmt).getExpr() or
result = this.(Assignment).getRhs()
}
override string describeQlClass() { result = "RecvStmt" }
}
/**
@@ -950,6 +1022,8 @@ class SelectStmt extends @selectstmt, Stmt {
override predicate mayHaveSideEffects() { any() }
override string toString() { result = "select statement" }
override string describeQlClass() { result = "SelectStmt" }
}
/**
@@ -1011,6 +1085,8 @@ class ForStmt extends @forstmt, LoopStmt {
}
override string toString() { result = "for statement" }
override string describeQlClass() { result = "ForStmt" }
}
/**
@@ -1051,4 +1127,6 @@ class RangeStmt extends @rangestmt, LoopStmt {
override predicate mayHaveSideEffects() { any() }
override string toString() { result = "range statement" }
override string describeQlClass() { result = "RangeStmt" }
}

View File

@@ -0,0 +1,592 @@
input.go:
# 0| [File] library-tests/semmle/go/PrintAst/input.go
# 3| 0: [ImportDecl] import declaration
# 3| 0: [ImportSpec] import specifier
# 3| 0: [StringLit] "fmt"
# 8| 1: [FuncDecl] function declaration
# 8| 0: [FunctionName, Ident] test5
# 8| Type = func(bool)
# 8| 1: [FuncTypeExpr] function type
# 8| 0: [ParameterDecl] parameter declaration
# 8| 0: [Ident, TypeName] bool
# 8| Type = bool
# 8| 1: [Ident, VariableName] b
# 8| Type = bool
# 8| 2: [BlockStmt] block statement
# 9| 0: [BlockStmt] block statement
# 10| 0: [IfStmt] if statement
# 10| 0: [NotExpr] !...
# 10| Type = bool
# 10| 0: [Ident, VariableName] b
# 10| Type = bool
# 10| 1: [BlockStmt] block statement
# 11| 0: [GotoStmt] goto statement
# 11| 0: [Ident, LabelName] outer
# 13| 1: [BlockStmt] block statement
# 15| 2: [EmptyStmt] empty statement
# 18| 1: [ExprStmt] expression statement
# 18| 0: [CallExpr] call to Println
# 18| Type = (int, error)
# 18| 0: [FunctionName, SelectorExpr] selection of Println
# 18| Type = func([]interface { }) int, error
# 18| 0: [Ident, PackageName] fmt
# 18| 1: [FunctionName, Ident] Println
# 18| Type = func([]interface { }) int, error
# 18| 1: [StringLit] "Hi"
# 18| Type = string
# 18| Value = [StringLit] Hi
# 20| 2: [LabelledStmt] labeled statement
# 20| 0: [Ident, LabelName] outer
# 21| 1: [ForStmt] for statement
# 21| 0: [ConstantName, Ident] true
# 21| Type = bool literal
# 21| Value = [ConstantName, Ident] true
# 21| 1: [BlockStmt] block statement
# 22| 0: [ForStmt] for statement
# 22| 0: [LssExpr] ...<...
# 22| Type = bool literal
# 22| 0: [Ident, VariableName] i
# 22| Type = int
# 22| 1: [IntLit] 10
# 22| Type = int
# 22| Value = [IntLit] 10
# 22| 1: [DefineStmt] ... := ...
# 22| 0: [Ident, VariableName] i
# 22| Type = int
# 22| 1: [IntLit] 0
# 22| Type = int
# 22| Value = [IntLit] 0
# 22| 2: [IncStmt] increment statement
# 22| 0: [Ident, VariableName] i
# 22| Type = int
# 22| 3: [BlockStmt] block statement
# 23| 0: [IfStmt] if statement
# 23| 0: [GtrExpr] ...>...
# 23| Type = bool literal
# 23| 0: [Ident, VariableName] j
# 23| Type = int
# 23| 1: [IntLit] 5
# 23| Type = int
# 23| Value = [IntLit] 5
# 23| 1: [DefineStmt] ... := ...
# 23| 0: [Ident, VariableName] j
# 23| Type = int
# 23| 1: [SubExpr] ...-...
# 23| Type = int
# 23| 0: [Ident, VariableName] i
# 23| Type = int
# 23| 1: [IntLit] 1
# 23| Type = int
# 23| Value = [IntLit] 1
# 23| 2: [BlockStmt] block statement
# 24| 0: [BreakStmt] break statement
# 24| 0: [Ident, LabelName] outer
# 25| 3: [IfStmt] if statement
# 25| 0: [LssExpr] ...<...
# 25| Type = bool literal
# 25| 0: [Ident, VariableName] i
# 25| Type = int
# 25| 1: [IntLit] 3
# 25| Type = int
# 25| Value = [IntLit] 3
# 25| 1: [BlockStmt] block statement
# 26| 0: [BreakStmt] break statement
# 27| 2: [IfStmt] if statement
# 27| 0: [NeqExpr] ...!=...
# 27| Type = bool literal
# 27| 0: [Ident, VariableName] i
# 27| Type = int
# 27| 1: [IntLit] 9
# 27| Type = int
# 27| Value = [IntLit] 9
# 27| 1: [BlockStmt] block statement
# 28| 0: [ContinueStmt] continue statement
# 28| 0: [Ident, LabelName] outer
# 29| 2: [IfStmt] if statement
# 29| 0: [GeqExpr] ...>=...
# 29| Type = bool literal
# 29| 0: [Ident, VariableName] i
# 29| Type = int
# 29| 1: [IntLit] 4
# 29| Type = int
# 29| Value = [IntLit] 4
# 29| 1: [BlockStmt] block statement
# 30| 0: [GotoStmt] goto statement
# 30| 0: [Ident, LabelName] outer
# 31| 2: [BlockStmt] block statement
# 32| 0: [ContinueStmt] continue statement
# 37| 3: [DefineStmt] ... := ...
# 37| 0: [Ident, VariableName] k
# 37| Type = int
# 37| 1: [IntLit] 9
# 37| Type = int
# 37| Value = [IntLit] 9
# 38| 4: [ForStmt] for statement
# 38| 0: [IncStmt] increment statement
# 38| 0: [Ident, VariableName] k
# 38| Type = int
# 38| 1: [BlockStmt] block statement
# 39| 0: [GotoStmt] goto statement
# 39| 0: [Ident, LabelName] outer
# 44| 2: [FuncDecl] function declaration
# 44| 0: [FunctionName, Ident] test6
# 44| Type = func(chan int, chan float32)
# 44| 1: [FuncTypeExpr] function type
# 44| 0: [ParameterDecl] parameter declaration
# 44| 0: [SendRecvChanTypeExpr] channel type
# 44| Type = chan int
# 44| 0: [Ident, TypeName] int
# 44| Type = int
# 44| 1: [Ident, VariableName] ch1
# 44| Type = chan int
# 44| 1: [ParameterDecl] parameter declaration
# 44| 0: [SendRecvChanTypeExpr] channel type
# 44| Type = chan float32
# 44| 0: [Ident, TypeName] float32
# 44| Type = float32
# 44| 1: [Ident, VariableName] ch2
# 44| Type = chan float32
# 44| 2: [BlockStmt] block statement
# 45| 0: [DeclStmt] declaration statement
# 45| 0: [VarDecl] variable declaration
# 45| 0: [ValueSpec] value declaration specifier
# 45| 0: [Ident, VariableName] a
# 45| Type = [1]float32
# 45| 1: [ArrayTypeExpr] array type
# 45| Type = [1]float32
# 45| 0: [IntLit] 1
# 45| Type = int literal
# 45| Value = [IntLit] 1
# 45| 1: [Ident, TypeName] float32
# 45| Type = float32
# 46| 1: [DeclStmt] declaration statement
# 46| 0: [VarDecl] variable declaration
# 46| 0: [ValueSpec] value declaration specifier
# 46| 0: [Ident, VariableName] w
# 46| Type = bool
# 46| 1: [Ident, TypeName] bool
# 46| Type = bool
# 48| 2: [SelectStmt] select statement
# 48| 0: [BlockStmt] block statement
# 49| 0: [CommClause] comm clause
# 49| 0: [ExprStmt, RecvStmt] expression statement
# 49| 0: [RecvExpr] <-...
# 49| Type = int
# 49| 0: [Ident, VariableName] ch1
# 49| Type = chan int
# 50| 1: [ExprStmt] expression statement
# 50| 0: [CallExpr] call to Println
# 50| Type = (int, error)
# 50| 0: [FunctionName, SelectorExpr] selection of Println
# 50| Type = func([]interface { }) int, error
# 50| 0: [Ident, PackageName] fmt
# 50| 1: [FunctionName, Ident] Println
# 50| Type = func([]interface { }) int, error
# 50| 1: [StringLit] "Heard from ch1"
# 50| Type = string
# 50| Value = [StringLit] Heard from ch1
# 51| 1: [CommClause] comm clause
# 51| 0: [AssignStmt, RecvStmt] ... = ...
# 51| 0: [Ident, VariableName] w
# 51| Type = bool
# 51| 1: [IndexExpr] index expression
# 51| Type = float32
# 51| 0: [Ident, VariableName] a
# 51| Type = [1]float32
# 51| 1: [IntLit] 0
# 51| Type = int
# 51| Value = [IntLit] 0
# 51| 2: [RecvExpr] <-...
# 51| Type = (float32, bool)
# 51| 0: [Ident, VariableName] ch2
# 51| Type = chan float32
# 52| 1: [ExprStmt] expression statement
# 52| 0: [CallExpr] call to Println
# 52| Type = (int, error)
# 52| 0: [FunctionName, SelectorExpr] selection of Println
# 52| Type = func([]interface { }) int, error
# 52| 0: [Ident, PackageName] fmt
# 52| 1: [FunctionName, Ident] Println
# 52| Type = func([]interface { }) int, error
# 52| 1: [Ident, VariableName] a
# 52| Type = [1]float32
# 53| 2: [ExprStmt] expression statement
# 53| 0: [CallExpr] call to Println
# 53| Type = (int, error)
# 53| 0: [FunctionName, SelectorExpr] selection of Println
# 53| Type = func([]interface { }) int, error
# 53| 0: [Ident, PackageName] fmt
# 53| 1: [FunctionName, Ident] Println
# 53| Type = func([]interface { }) int, error
# 53| 1: [Ident, VariableName] w
# 53| Type = bool
# 54| 2: [CommClause] comm clause
# 55| 0: [ExprStmt] expression statement
# 55| 0: [CallExpr] call to Println
# 55| Type = (int, error)
# 55| 0: [FunctionName, SelectorExpr] selection of Println
# 55| Type = func([]interface { }) int, error
# 55| 0: [Ident, PackageName] fmt
# 55| 1: [FunctionName, Ident] Println
# 55| Type = func([]interface { }) int, error
# 56| 3: [CommClause] comm clause
# 56| 0: [SendStmt] send statement
# 56| 0: [Ident, VariableName] ch1
# 56| Type = chan int
# 56| 1: [IntLit] 42
# 56| Type = int
# 56| Value = [IntLit] 42
# 59| 3: [SelectStmt] select statement
# 59| 0: [BlockStmt] block statement
# 63| 3: [FuncDecl] function declaration
# 63| 0: [FunctionName, Ident] test7
# 63| Type = func(int) int
# 63| 1: [FuncTypeExpr] function type
# 63| 0: [ResultVariableDecl] result variable declaration
# 63| 0: [Ident, TypeName] int
# 63| Type = int
# 63| 1: [ParameterDecl] parameter declaration
# 63| 0: [Ident, TypeName] int
# 63| Type = int
# 63| 1: [Ident, VariableName] x
# 63| Type = int
# 63| 2: [BlockStmt] block statement
# 64| 0: [IfStmt] if statement
# 64| 0: [GtrExpr] ...>...
# 64| Type = bool literal
# 64| 0: [Ident, VariableName] x
# 64| Type = int
# 64| 1: [IntLit] 0
# 64| Type = int
# 64| Value = [IntLit] 0
# 64| 1: [BlockStmt] block statement
# 65| 0: [DeferStmt] defer statement
# 65| 0: [CallExpr] function call
# 65| Type = ()
# 65| 0: [FuncLit] function literal
# 65| Type = func()
# 65| 0: [FuncTypeExpr] function type
# 65| Type = func()
# 65| 1: [BlockStmt] block statement
# 65| 0: [ExprStmt] expression statement
# 65| 0: [CallExpr] call to Println
# 65| Type = (int, error)
# 65| 0: [FunctionName, SelectorExpr] selection of Println
# 65| Type = func([]interface { }) int, error
# 65| 0: [Ident, PackageName] fmt
# 65| 1: [FunctionName, Ident] Println
# 65| Type = func([]interface { }) int, error
# 65| 1: [Ident, VariableName] x
# 65| Type = int
# 66| 2: [BlockStmt] block statement
# 67| 0: [DeferStmt] defer statement
# 67| 0: [CallExpr] function call
# 67| Type = ()
# 67| 0: [FuncLit] function literal
# 67| Type = func()
# 67| 0: [FuncTypeExpr] function type
# 67| Type = func()
# 67| 1: [BlockStmt] block statement
# 67| 0: [ExprStmt] expression statement
# 67| 0: [CallExpr] call to Println
# 67| Type = (int, error)
# 67| 0: [FunctionName, SelectorExpr] selection of Println
# 67| Type = func([]interface { }) int, error
# 67| 0: [Ident, PackageName] fmt
# 67| 1: [FunctionName, Ident] Println
# 67| Type = func([]interface { }) int, error
# 67| 1: [MinusExpr] -...
# 67| Type = int
# 67| 0: [Ident, VariableName] x
# 67| Type = int
# 69| 1: [ReturnStmt] return statement
# 69| 0: [IntLit] 42
# 69| Type = int
# 69| Value = [IntLit] 42
# 73| 4: [FuncDecl] function declaration
# 73| 0: [FunctionName, Ident] test8
# 73| Type = func(int)
# 73| 1: [FuncTypeExpr] function type
# 73| 0: [ParameterDecl] parameter declaration
# 73| 0: [Ident, TypeName] int
# 73| Type = int
# 73| 1: [Ident, VariableName] x
# 73| Type = int
# 73| 2: [BlockStmt] block statement
# 74| 0: [ExpressionSwitchStmt] expression-switch statement
# 74| 0: [Ident, VariableName] x
# 74| Type = int
# 74| 1: [BlockStmt] block statement
# 77| 1: [ExpressionSwitchStmt] expression-switch statement
# 77| 0: [SubExpr] ...-...
# 77| Type = int
# 77| 0: [Ident, VariableName] y
# 77| Type = int
# 77| 1: [IntLit] 19
# 77| Type = int
# 77| Value = [IntLit] 19
# 77| 1: [DefineStmt] ... := ...
# 77| 0: [Ident, VariableName] y
# 77| Type = int
# 77| 1: [Ident, VariableName] x
# 77| Type = int
# 77| 2: [BlockStmt] block statement
# 78| 0: [CaseClause] case clause
# 79| 0: [ExprStmt] expression statement
# 79| 0: [CallExpr] call to test5
# 79| Type = ()
# 79| 0: [FunctionName, Ident] test5
# 79| Type = func(bool)
# 79| 1: [ConstantName, Ident] false
# 79| Type = bool
# 79| Value = [ConstantName, Ident] false
# 82| 2: [ExpressionSwitchStmt] expression-switch statement
# 82| 0: [Ident, VariableName] x
# 82| Type = int
# 82| 1: [BlockStmt] block statement
# 83| 0: [CaseClause] case clause
# 83| 0: [IntLit] 1
# 83| Type = int
# 83| Value = [IntLit] 1
# 84| 1: [CaseClause] case clause
# 84| 0: [IntLit] 3
# 84| Type = int
# 84| Value = [IntLit] 3
# 84| 1: [IntLit] 2
# 84| Type = int
# 84| Value = [IntLit] 2
# 85| 2: [ExprStmt] expression statement
# 85| 0: [CallExpr] call to test5
# 85| Type = ()
# 85| 0: [FunctionName, Ident] test5
# 85| Type = func(bool)
# 85| 1: [ConstantName, Ident] true
# 85| Type = bool
# 85| Value = [ConstantName, Ident] true
# 88| 3: [ExpressionSwitchStmt] expression-switch statement
# 88| 0: [Ident, VariableName] x
# 88| Type = int
# 88| 1: [BlockStmt] block statement
# 89| 0: [CaseClause] case clause
# 89| 0: [IntLit] 1
# 89| Type = int
# 89| Value = [IntLit] 1
# 90| 1: [ExprStmt] expression statement
# 90| 0: [CallExpr] call to test5
# 90| Type = ()
# 90| 0: [FunctionName, Ident] test5
# 90| Type = func(bool)
# 90| 1: [ConstantName, Ident] false
# 90| Type = bool
# 90| Value = [ConstantName, Ident] false
# 91| 2: [FallthroughStmt] fallthrough statement
# 92| 1: [CaseClause] case clause
# 92| 0: [SubExpr] ...-...
# 92| Type = int
# 92| Value = [SubExpr] -3
# 92| 0: [IntLit] 2
# 92| Type = int literal
# 92| Value = [IntLit] 2
# 92| 1: [IntLit] 5
# 92| Type = int literal
# 92| Value = [IntLit] 5
# 93| 1: [ExprStmt] expression statement
# 93| 0: [CallExpr] call to test5
# 93| Type = ()
# 93| 0: [FunctionName, Ident] test5
# 93| Type = func(bool)
# 93| 1: [ConstantName, Ident] true
# 93| Type = bool
# 93| Value = [ConstantName, Ident] true
# 96| 4: [ExpressionSwitchStmt] expression-switch statement
# 96| 0: [Ident, VariableName] x
# 96| Type = int
# 96| 1: [BlockStmt] block statement
# 97| 0: [CaseClause] case clause
# 98| 1: [CaseClause] case clause
# 98| 0: [IntLit] 2
# 98| Type = int
# 98| Value = [IntLit] 2
# 99| 1: [ExprStmt] expression statement
# 99| 0: [CallExpr] call to test5
# 99| Type = ()
# 99| 0: [FunctionName, Ident] test5
# 99| Type = func(bool)
# 99| 1: [ConstantName, Ident] true
# 99| Type = bool
# 99| Value = [ConstantName, Ident] true
# 102| 5: [ExpressionSwitchStmt] expression-switch statement
# 102| 0: [BlockStmt] block statement
# 103| 0: [CaseClause] case clause
# 104| 0: [BreakStmt] break statement
# 105| 1: [CaseClause] case clause
# 105| 0: [ConstantName, Ident] true
# 105| Type = bool
# 105| Value = [ConstantName, Ident] true
# 110| 5: [FuncDecl] function declaration
# 110| 0: [FunctionName, Ident] test9
# 110| Type = func(interface { })
# 110| 1: [FuncTypeExpr] function type
# 110| 0: [ParameterDecl] parameter declaration
# 110| 0: [InterfaceTypeExpr] interface type
# 110| Type = interface { }
# 110| 1: [Ident, VariableName] x
# 110| Type = interface { }
# 110| 2: [BlockStmt] block statement
# 111| 0: [TypeSwitchStmt] type-switch statement
# 111| 0: [DefineStmt] ... := ...
# 111| 0: [Ident] y
# 111| 1: [TypeAssertExpr] type assertion
# 111| 0: [Ident, VariableName] x
# 111| Type = interface { }
# 111| 1: [BlockStmt] block statement
# 112| 0: [CaseClause] case clause
# 112| 0: [Ident, TypeName] string
# 112| Type = string
# 112| 1: [Ident, TypeName] error
# 112| Type = error
# 113| 2: [ExprStmt] expression statement
# 113| 0: [CallExpr] call to Println
# 113| Type = (int, error)
# 113| 0: [FunctionName, SelectorExpr] selection of Println
# 113| Type = func([]interface { }) int, error
# 113| 0: [Ident, PackageName] fmt
# 113| 1: [FunctionName, Ident] Println
# 113| Type = func([]interface { }) int, error
# 113| 1: [Ident, VariableName] y
# 113| Type = interface { }
# 114| 1: [CaseClause] case clause
# 114| 0: [Ident, TypeName] float32
# 114| Type = float32
# 115| 1: [ExprStmt] expression statement
# 115| 0: [CallExpr] call to test5
# 115| Type = ()
# 115| 0: [FunctionName, Ident] test5
# 115| Type = func(bool)
# 115| 1: [ConstantName, Ident] true
# 115| Type = bool
# 115| Value = [ConstantName, Ident] true
# 116| 2: [ExprStmt] expression statement
# 116| 0: [CallExpr] call to test5
# 116| Type = ()
# 116| 0: [FunctionName, Ident] test5
# 116| Type = func(bool)
# 116| 1: [ConstantName, Ident] false
# 116| Type = bool
# 116| Value = [ConstantName, Ident] false
# 119| 1: [TypeSwitchStmt] type-switch statement
# 119| 0: [DefineStmt] ... := ...
# 119| 0: [Ident, VariableName] y
# 119| Type = interface { }
# 119| 1: [Ident, VariableName] x
# 119| Type = interface { }
# 119| 1: [ExprStmt] expression statement
# 119| 0: [TypeAssertExpr] type assertion
# 119| 0: [Ident, VariableName] y
# 119| Type = interface { }
# 119| 2: [BlockStmt] block statement
# 120| 0: [CaseClause] case clause
# 121| 0: [ExprStmt] expression statement
# 121| 0: [CallExpr] call to test5
# 121| Type = ()
# 121| 0: [FunctionName, Ident] test5
# 121| Type = func(bool)
# 121| 1: [ConstantName, Ident] false
# 121| Type = bool
# 121| Value = [ConstantName, Ident] false
# 126| 6: [FuncDecl] function declaration
# 126| 0: [FunctionName, Ident] test10
# 126| Type = func(func() )
# 126| 1: [FuncTypeExpr] function type
# 126| 0: [ParameterDecl] parameter declaration
# 126| 0: [FuncTypeExpr] function type
# 126| Type = func()
# 126| 1: [Ident, VariableName] f
# 126| Type = func()
# 126| 2: [BlockStmt] block statement
# 127| 0: [GoStmt] go statement
# 127| 0: [CallExpr] call to f
# 127| Type = ()
# 127| 0: [Ident, VariableName] f
# 127| Type = func()
# 131| 7: [FuncDecl] function declaration
# 131| 0: [FunctionName, Ident] test11
# 131| Type = func([]int)
# 131| 1: [FuncTypeExpr] function type
# 131| 0: [ParameterDecl] parameter declaration
# 131| 0: [ArrayTypeExpr] array type
# 131| Type = []int
# 131| 0: [Ident, TypeName] int
# 131| Type = int
# 131| 1: [Ident, VariableName] xs
# 131| Type = []int
# 131| 2: [BlockStmt] block statement
# 132| 0: [RangeStmt] range statement
# 132| 0: [Ident, VariableName] x
# 132| Type = int
# 132| 1: [Ident, VariableName] xs
# 132| Type = []int
# 132| 2: [BlockStmt] block statement
# 133| 0: [IfStmt] if statement
# 133| 0: [GtrExpr] ...>...
# 133| Type = bool literal
# 133| 0: [Ident, VariableName] x
# 133| Type = int
# 133| 1: [IntLit] 5
# 133| Type = int
# 133| Value = [IntLit] 5
# 133| 1: [BlockStmt] block statement
# 134| 0: [ContinueStmt] continue statement
# 136| 1: [ExprStmt] expression statement
# 136| 0: [CallExpr] call to Print
# 136| Type = (int, error)
# 136| 0: [FunctionName, SelectorExpr] selection of Print
# 136| Type = func([]interface { }) int, error
# 136| 0: [Ident, PackageName] fmt
# 136| 1: [FunctionName, Ident] Print
# 136| Type = func([]interface { }) int, error
# 136| 1: [Ident, VariableName] x
# 136| Type = int
# 139| 1: [RangeStmt] range statement
# 139| 0: [Ident, VariableName] i
# 139| Type = int
# 139| 1: [Ident, VariableName] v
# 139| Type = int
# 139| 2: [Ident, VariableName] xs
# 139| Type = []int
# 139| 3: [BlockStmt] block statement
# 140| 0: [ExprStmt] expression statement
# 140| 0: [CallExpr] call to Print
# 140| Type = (int, error)
# 140| 0: [FunctionName, SelectorExpr] selection of Print
# 140| Type = func([]interface { }) int, error
# 140| 0: [Ident, PackageName] fmt
# 140| 1: [FunctionName, Ident] Print
# 140| Type = func([]interface { }) int, error
# 140| 1: [Ident, VariableName] i
# 140| Type = int
# 140| 2: [Ident, VariableName] v
# 140| Type = int
# 143| 2: [RangeStmt] range statement
# 143| 0: [Ident, VariableName] xs
# 143| Type = []int
# 143| 1: [BlockStmt] block statement
# 1| 8: [Ident] main
# 7| [DocComment] comment group
# 43| [DocComment] comment group
# 62| [DocComment] comment group
# 72| [DocComment] comment group
# 109| [DocComment] comment group
# 125| [DocComment] comment group
# 130| [DocComment] comment group
# 5| [CommentGroup] comment group
# 5| [SlashSlashComment] comment
# 7| [SlashSlashComment] comment
# 15| [CommentGroup] comment group
# 15| [SlashSlashComment] comment
# 43| [SlashSlashComment] comment
# 62| [SlashSlashComment] comment
# 72| [SlashSlashComment] comment
# 109| [SlashSlashComment] comment
# 125| [SlashSlashComment] comment
# 130| [SlashSlashComment] comment

View File

@@ -0,0 +1,6 @@
/**
* @kind graph
*/
import go
import semmle.go.PrintAst

View File

@@ -0,0 +1,145 @@
package main
import "fmt"
// NOTE: after auto-formatting this file, make sure to put back the empty statement on line 15 below
// simple statements and for loops
func test5(b bool) {
{
if !b {
goto outer
}
{
}
; // empty statement
}
fmt.Println("Hi")
outer:
for true {
for i := 0; i < 10; i++ {
if j := i - 1; j > 5 {
break outer
} else if i < 3 {
break
} else if i != 9 {
continue outer
} else if i >= 4 {
goto outer
} else {
continue
}
}
}
k := 9
for ; ; k++ {
goto outer
}
}
// select
func test6(ch1 chan int, ch2 chan float32) {
var a [1]float32
var w bool
select {
case <-ch1:
fmt.Println("Heard from ch1")
case a[0], w = <-ch2:
fmt.Println(a)
fmt.Println(w)
default:
fmt.Println()
case ch1 <- 42:
}
select {}
}
// defer
func test7(x int) int {
if x > 0 {
defer func() { fmt.Println(x) }()
} else {
defer func() { fmt.Println(-x) }()
}
return 42
}
// expression switch
func test8(x int) {
switch x {
}
switch y := x; y - 19 {
default:
test5(false)
}
switch x {
case 1:
case 2, 3:
test5(true)
}
switch x {
case 1:
test5(false)
fallthrough
case 2 - 5:
test5(true)
}
switch x {
default:
case 2:
test5(true)
}
switch {
default:
break
case true:
}
}
// type switch
func test9(x interface{}) {
switch y := x.(type) {
case error, string:
fmt.Println(y)
case float32:
test5(true)
test5(false)
}
switch y := x; y.(type) {
default:
test5(false)
}
}
// go
func test10(f func()) {
go f()
}
// more loops
func test11(xs []int) {
for x := range xs {
if x > 5 {
continue
}
fmt.Print(x)
}
for i, v := range xs {
fmt.Print(i, v)
}
for range xs {
}
}