private import codeql_ruby.AST private import codeql_ruby.controlflow.ControlFlowGraph private import internal.AST private import internal.TreeSitter /** A callable. */ class Callable extends Expr, Scope, TCallable { /** Gets the number of parameters of this callable. */ final int getNumberOfParameters() { result = count(this.getAParameter()) } /** Gets a parameter of this callable. */ final Parameter getAParameter() { result = this.getParameter(_) } /** Gets the `n`th parameter of this callable. */ Parameter getParameter(int n) { none() } override AstNode getAChild(string pred) { pred = "getParameter" and result = this.getParameter(_) } } /** A method. */ class MethodBase extends Callable, BodyStmt, Scope, TMethodBase { /** Gets the name of this method. */ string getName() { none() } override AstNode getAChild(string pred) { result = Callable.super.getAChild(pred) or result = BodyStmt.super.getAChild(pred) } } /** A normal method. */ class Method extends MethodBase, TMethod { private Generated::Method g; Method() { this = TMethod(g) } final override string getAPrimaryQlClass() { result = "Method" } final override string getName() { result = g.getName().(Generated::Token).getValue() or result = g.getName().(Generated::Setter).getName().getValue() + "=" } /** * Holds if this is a setter method, as in the following example: * ```rb * class Person * def name=(n) * @name = n * end * end * ``` */ final predicate isSetter() { g.getName() instanceof Generated::Setter } final override Parameter getParameter(int n) { toGenerated(result) = g.getParameters().getChild(n) } final override string toString() { result = this.getName() } } /** A singleton method. */ class SingletonMethod extends MethodBase, TSingletonMethod { private Generated::SingletonMethod g; SingletonMethod() { this = TSingletonMethod(g) } final override string getAPrimaryQlClass() { result = "SingletonMethod" } /** Gets the object of this singleton method. */ final Expr getObject() { toGenerated(result) = g.getObject() } final override string getName() { result = g.getName().(Generated::Token).getValue() or result = g.getName().(Generated::Setter).getName().getValue() + "=" } final override Parameter getParameter(int n) { toGenerated(result) = g.getParameters().getChild(n) } final override string toString() { result = this.getName() } final override AstNode getAChild(string pred) { result = MethodBase.super.getAChild(pred) or pred = "getObject" and result = this.getObject() } } /** * A lambda (anonymous method). For example: * ```rb * -> (x) { x + 1 } * ``` */ class Lambda extends Callable, BodyStmt, TLambda { private Generated::Lambda g; Lambda() { this = TLambda(g) } final override string getAPrimaryQlClass() { result = "Lambda" } final override Parameter getParameter(int n) { toGenerated(result) = g.getParameters().getChild(n) } final override string toString() { result = "-> { ... }" } final override AstNode getAChild(string pred) { result = Callable.super.getAChild(pred) or result = BodyStmt.super.getAChild(pred) } } /** A block. */ class Block extends Callable, StmtSequence, Scope, TBlock { override AstNode getAChild(string pred) { result = Callable.super.getAChild(pred) or result = StmtSequence.super.getAChild(pred) } } /** A block enclosed within `do` and `end`. */ class DoBlock extends Block, BodyStmt, TDoBlock { private Generated::DoBlock g; DoBlock() { this = TDoBlock(g) } final override Parameter getParameter(int n) { toGenerated(result) = g.getParameters().getChild(n) } final override string toString() { result = "do ... end" } final override AstNode getAChild(string pred) { result = Block.super.getAChild(pred) or result = BodyStmt.super.getAChild(pred) } final override string getAPrimaryQlClass() { result = "DoBlock" } } /** * A block defined using curly braces, e.g. in the following code: * ```rb * names.each { |name| puts name } * ``` */ class BraceBlock extends Block, TBraceBlock { private Generated::Block g; BraceBlock() { this = TBraceBlock(g) } final override Parameter getParameter(int n) { toGenerated(result) = g.getParameters().getChild(n) } final override Stmt getStmt(int i) { toGenerated(result) = g.getChild(i) } final override string toString() { result = "{ ... }" } final override string getAPrimaryQlClass() { result = "BraceBlock" } }