Abstract syntax tree classes for working with Ruby programs¶
CodeQL has a large selection of classes for representing the abstract syntax tree of Ruby programs.
The abstract syntax tree (AST) represents the syntactic structure of a program. Nodes on the AST represent elements such as statements and expressions.
The descriptions below use the following conventions and placeholders.
- An
IDENTIFIER
denotes an arbitrary identifier. - A
CNAME
denotes a class or module name. - An
FNAME
denotes a method name. - A
TERM
is either a semicolon or a newline used to terminate a statement. - Elements enclosed in
« »
are grouped and may be suffixed by?
,*
, or+
to denote 0 or 1 occurrences, 0 or more occurrences, and 1 or more occurrences respectively.
Statement classes¶
This table lists subclasses of Stmt that represent Ruby statements.
Statement syntax | CodeQL class | Superclasses | Remarks |
---|---|---|---|
alias FNAME FNAME |
AliasStmt | Stmt | |
BEGIN { StmtSequence } |
BeginBlock | StmtSequence | |
begin StmtSequence end |
BeginExpr | StmtSequence | |
break «Expr»? |
BreakStmt | ReturningStmt | |
; |
EmptyStmt | Stmt | |
END { StmtSequence } |
EndBlock | StmtSequence | |
next «Expr»? |
NextStmt | ReturningStmt | |
redo |
RedoStmt | Stmt | |
retry |
RetryStmt | Stmt | |
return «Expr»? |
ReturnStmt | ReturningStmt | |
undef «FNAME , »+ |
UndefStmt | Stmt |
Calls¶
This table lists subclasses of Call as well as some expressions that appear as call arguments.
Expression syntax | CodeQL class | Superclasses | Remarks |
---|---|---|---|
Expr [ Expr ] |
ElementReference | MethodCall | |
MethodName «Expr , »* |
MethodCall | Call | |
LhsExpr = Expr |
SetterMethodCall | MethodCall | |
super |
SuperCall | MethodCall | |
yield «Expr , »* |
YieldCall | Call | |
& IDENTIFIER |
BlockArgument | Expr | Used as an argument to a call |
... |
ForwardedArguments | Expr | Used as an argument to a call |
Constant accesses¶
All classes in this subsection are subclasses of ConstantAccess.
Expression syntax | CodeQL class | Superclasses | Remarks |
---|---|---|---|
CNAME | ConstantReadAccess | ConstantAccess | |
CNAME = Expr |
ConstantAssignment | ConstantWriteAccess |
Control expressions¶
All classes in this subsection are subclasses of ControlExpr.
Expression syntax | CodeQL class | Superclasses | Remarks |
---|---|---|---|
if Expr then StmtSequence «elsif Expr then StmtSequence»* «else StmtSequence»? end |
IfExpr | ConditionalExpr, ControlExpr | |
while Expr do StmtSequence end |
WhileExpr | ConditionalLoop | |
until Expr do StmtSequence end |
UntilExpr | ConditionalLoop | |
for LhsExpr in Expr do StmtSequence end |
ForExpr | Loop | |
Stmt while Expr |
WhileModifierExpr | ConditionalLoop | |
Stmt until Expr |
UntilModifierExpr | ConditionalLoop | |
Stmt if Expr |
IfModifierExpr | ConditionalExpr, ControlExpr | |
Stmt unless Expr |
UnlessModifierExpr | ConditionalExpr, ControlExpr | |
Expr ? Stmt : Stmt |
TernaryIfExpr | ConditionalExpr, ControlExpr | |
case Expr when Expr then StmtSequence «when Expr then StmtSequence»* «else StmtSequence»? end |
CaseExpr | ControlExpr | |
case when Expr then StmtSequence «else StmtSequence»? end |
CaseExpr | ControlExpr | |
case Expr in «TERM CaseExpr»+ end f |
CaseExpr | ControlExpr |
Unary operations¶
All classes in this subsection are subclasses of UnaryOperation.
Expression syntax | CodeQL class | Superclasses | Remarks | |
---|---|---|---|
~ Expr |
ComplementExpr | UnaryBitwiseOperation | |
defined? Expr |
DefinedExpr | UnaryOperation | |
** Expr |
HashSplatExpr | UnaryOperation | |
! Expr |
NotExpr | UnaryOperation | |
not Expr |
NotExpr | UnaryOperation | |
* Expr |
SplatExpr | UnaryOperation | |
- Expr |
UnaryMinusExpr | UnaryArithmeticOperation | |
+ Expr |
UnaryPlusExpr | UnaryArithmeticOperation |
Binary operations¶
All classes in this subsection are subclasses of BinaryOperation.
Literals¶
All classes in this subsection are subclasses of Literal.
Example expression syntax | CodeQL class | Superclasses | Remarks |
---|---|---|---|
[1, 2] |
ArrayLiteral | Literal | |
true |
BooleanLiteral | Literal | |
?a |
CharacterLiteral | Literal | |
__ENCODING__ |
EncodingLiteral | Literal | |
__FILE__ |
FileLiteral | Literal | |
{ foo: 123, bar: 456 } |
HashLiteral | Literal | |
<<FOO hello world FOO |
HereDoc | StringlikeLiteral | |
23 |
IntegerLiteral | NumericLiteral | |
3.1 |
FloatLiteral | NumericLiteral | |
3+2i |
ComplexLiteral | NumericLiteral | |
2/3r |
RationalLiteral | NumericLiteral | |
__LINE__ |
LineLiteral | Literal | |
nil |
NilLiteral | Literal | |
(1..10) |
RangeLiteral | Literal | |
/[a-z]+/ |
RegExpLiteral | StringlikeLiteral | |
"hello world" |
StringLiteral | StringlikeLiteral | |
`ls -l` |
SubshellLiteral | StringlikeLiteral | |
%x(/bin/sh foo.sh) |
SubshellLiteral | StringlikeLiteral | |
:foo |
SymbolLiteral | StringlikeLiteral |
Modules and Ruby classes¶
All classes in this subsection are subclasses of BodyStmt and Scope.
Expression syntax | CodeQL class | Superclasses | Remarks |
---|---|---|---|
class CNAME «< Expr»? TERM StmtSequence TERM end |
ClassDeclaration | Namespace, ConstantWriteAccess | |
module CNAME TERM StmtSequence TERM end |
ModuleDeclaration | Namespace, ConstantWriteAccess | |
class << Expr TERM StmtSequence TERM end |
SingletonClass | ModuleBase |
Callable classes¶
All classes in this subsection are subclasses of Callable.
Expression syntax | CodeQL class | Superclasses | Remarks |
---|---|---|---|
{ «| «Parameter , »* | »? StmtSequence } |
BraceBlock | Block | |
do «| «Parameter , »* | »? BodyStmt end |
DoBlock | Block, BodyStmt | |
-> ( «Parameter , »* ) { StmtSequence } |
Lambda | Callable, BodyStmt | |
-> ( «Parameter , »* ) do BodyStmt end |
Lambda | Callable, BodyStmt | |
def FNAME «Parameter , »* TERM BodyStmt TERM end |
Method | MethodBase | |
def self. FNAME «Parameter , »* TERM BodyStmt TERM end |
SingletonMethod | MethodBase |
Parameter classes¶
All classes in this subsection are subclasses of Parameter.
Expression syntax | CodeQL class | Superclasses | Remarks |
---|---|---|---|
& IDENTIFIER |
BlockParameter | NamedParameter | |
( «IDENTIFIER , »+ ) |
DestructuredParameter | ||
... |
ForwardParameter | ||
**nil |
HashSplatNilParameter | Indicates that there are no keyword parameters or keyword patterns | |
** IDENTIFIER |
HashSplatParameter | NamedParameter | |
IDENTIFIER : «Expr»? |
KeywordParameter | NamedParameter | |
IDENTIFIER = Expr |
OptionalParameter | NamedParameter | |
IDENTIFIER | SimpleParameter | NamedParameter | |
* IDENTIFIER |
SplatParameter | NamedParameter |
Pattern classes¶
All classes in this subsection are subclasses of CasePattern. These expressions typically occur when a case
uses pattern matching syntax.
Expression syntax | CodeQL class | Superclasses | Remarks |
---|---|---|---|
CasePattern «| CasePattern»+ |
AlternativePattern | CasePattern | |
[ «CasePattern , »* «* IDENTIFIER»? ] |
ArrayPattern | CasePattern | |
CasePattern => IDENTIFIER |
AsPattern | CasePattern | |
[ * «IDENTIFIER»? (, CasePattern)* , * «IDENTIFIER»? ] |
FindPattern | CasePattern | |
{ «StringlikeLiteral : CasePattern , »* «** IDENTIFIER»? } |
HashPattern | CasePattern | |
( CasePattern ) |
ParenthesizedPattern | CasePattern | |
^ Expr |
ReferencePattern | CasePattern |
Expression classes¶
All classes in this subsection are subclasses of Expr.
Expression syntax | CodeQL class | Superclasses | Remarks |
---|---|---|---|
«Expr , »+ |
ArgumentList | Expr | The right-hand side of an assignment or a return , break , or next statement |
StmtSequence «RescueClause»? «else StmtSequence»? «ensure StmtSequence»? |
BodyStmt | StmtSequence | |
Expr «, Expr»+ |
DestructuredLhsExpr | LhsExpr | |
Expr | LhsExpr | Expr | An Expr appearing on the left-hand side of various operations. Can take many forms. |
Expr : Expr |
Pair | Expr | Such as in a hash or as a keyword argument |
( StmtSequence ) |
ParenthesizedExpr | StmtSequence | |
rescue StmtSequence |
RescueClause | Expr | |
Stmt rescue Stmt |
RescueModifierExpr | Expr | |
StmtSequence TERM Stmt | StmtSequence | Expr | A sequence of 0 or more statements, separated by semicolons or newlines |
StringLiteral StringLiteral | StringConcatenation | Expr | Implicit concatenation of consecutive string literals |
Variable classes¶
All classes in this subsection are subclasses of VariableAccess.
Example expression syntax | CodeQL class | Superclasses | Remarks |
---|---|---|---|
@@foo |
ClassVariableReadAccess | VariableReadAccess, ClassVariableAccess | |
@@foo = 'str' |
ClassVariableWriteAccess | VariableWriteAccess, ClassVariableAccess | |
$foo |
GlobalVariableReadAccess | VariableReadAccess, GlobalVariableAccess | |
$foo = 'str' |
GlobalVariableWriteAccess | VariableWriteAccess, GlobalVariableAccess | |
@foo |
InstanceVariableReadAccess | VariableReadAccess, InstanceVariableAccess | |
@foo = 'str' |
InstanceVariableWriteAccess | VariableWriteAccess, InstanceVariableAccess | |
foo |
LocalVariableReadAccess | VariableReadAccess, LocalVariableAccess | |
foo = 'str' |
LocalVariableWriteAccess | VariableWriteAccess, LocalVariableAccess | |
self |
SelfVariableReadAccess | VariableReadAccess, SelfVariableAccess |
Syntactic sugar and desugaring¶
Certain Ruby language features are shorthands for common operations that could also be expressed in other, more verbose, forms. Such language features are typically referred to as “syntactic sugar”, and make it easier for programmers to write and read code. This is great for programmers. For source code analyzers, however, this leads to additional work as they need to understand the shorthand notation as well as the long form. To make analysis easier, CodeQL automatically “desugars” Ruby code, effectively rewriting rich syntactic constructs into equivalent code that uses simpler syntactic constructs.
For example, supposing that x
is an object with an attribute foo
, the assignment:
x.foo = y
is desugared to code similar to:
x.foo=(__synth_0 = y);
__synth_0;
In other words, there is effectively a call to the SetterMethodCall foo=
on x
with argument __synth_0 = y
, followed by a read of the __synth_0
variable.
In CodeQL, this is implemented by synthesizing AstNode instances corresponding to this desugared version of the code.
Note that the original AssignExpr and the desugared SetterMethodCall versions are both available to use in CodeQL queries, and you do not usually need to be aware of any desugaring that may take place. However, if a codebase explicitly uses x.foo=(y)
SetterMethodCall syntax, you cannot find this syntax by searching for instances of AssignExpr .
Other synthesized AstNode instances exist, see the isSynthesized and getDesugared predicates for details.