mirror of
https://github.com/github/codeql.git
synced 2026-01-30 06:42:57 +01:00
Merge pull request #179 from smowton/smowton/feature/printast
Add barebones PrintAST for Go
This commit is contained in:
@@ -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" }
|
||||
}
|
||||
|
||||
|
||||
@@ -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>*/</code>.
|
||||
@@ -132,7 +140,9 @@ class SlashSlashComment extends @slashslashcomment, Comment { }
|
||||
* comment */
|
||||
* </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" }
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
16
ql/src/semmle/go/PrintAst.ql
Normal file
16
ql/src/semmle/go/PrintAst.ql
Normal 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() }
|
||||
}
|
||||
209
ql/src/semmle/go/PrintAst.qll
Normal file
209
ql/src/semmle/go/PrintAst.qll
Normal 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"
|
||||
}
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
592
ql/test/library-tests/semmle/go/PrintAst/PrintAst.expected
Normal file
592
ql/test/library-tests/semmle/go/PrintAst/PrintAst.expected
Normal 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
|
||||
6
ql/test/library-tests/semmle/go/PrintAst/PrintAst.ql
Normal file
6
ql/test/library-tests/semmle/go/PrintAst/PrintAst.ql
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @kind graph
|
||||
*/
|
||||
|
||||
import go
|
||||
import semmle.go.PrintAst
|
||||
145
ql/test/library-tests/semmle/go/PrintAst/input.go
Normal file
145
ql/test/library-tests/semmle/go/PrintAst/input.go
Normal 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 {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user