用于处理 Ruby 程序的抽象语法树类¶
CodeQL 拥有大量用于表示 Ruby 程序抽象语法树的类。
抽象语法树 (AST) 表示程序的语法结构。AST 上的节点表示语句和表达式等元素。
以下描述使用以下约定和占位符。
- 一个
IDENTIFIER
表示任意标识符。 - 一个
CNAME
表示类或模块名称。 - 一个
FNAME
表示方法名称。 - 一个
TERM
是分号或换行符,用于终止语句。 - 用
« »
括起来的元素被分组,可能以?
、*
或+
为后缀,分别表示 0 或 1 次出现、0 或多次出现和 1 或多次出现。
语句类¶
此表列出了 Stmt 的子类,这些子类表示 Ruby 语句。
语句语法 | CodeQL 类 | 超类 | 备注 |
---|---|---|---|
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 |
调用¶
此表列出了 Call 的子类,以及一些作为调用参数出现的表达式。
表达式语法 | CodeQL 类 | 超类 | 备注 |
---|---|---|---|
Expr [ Expr ] |
ElementReference | MethodCall | |
MethodName «Expr , »* |
MethodCall | Call | |
LhsExpr = Expr |
SetterMethodCall | MethodCall | |
super |
SuperCall | MethodCall | |
yield «Expr , »* |
YieldCall | Call | |
& IDENTIFIER |
BlockArgument | Expr | 用作调用参数 |
... |
ForwardedArguments | Expr | 用作调用参数 |
常量访问¶
本节中的所有类都是 ConstantAccess 的子类。
表达式语法 | CodeQL 类 | 超类 | 备注 |
---|---|---|---|
CNAME | ConstantReadAccess | ConstantAccess | |
CNAME = Expr |
ConstantAssignment | ConstantWriteAccess |
控制表达式¶
本节中的所有类都是 ControlExpr 的子类。
表达式语法 | CodeQL 类 | 超类 | 备注 |
---|---|---|---|
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 |
一元运算¶
本节中的所有类都是 UnaryOperation 的子类。
表达式语法 | CodeQL 类 | 父类 | 备注 | |
---|---|---|---|
~ 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 |
二元运算符¶
本节中所有类都是 BinaryOperation 的子类。
字面量¶
本节中所有类都是 Literal 的子类。
示例表达式语法 | CodeQL 类 | 超类 | 备注 |
---|---|---|---|
[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 |
模块和 Ruby 类¶
本小节中的所有类都是 BodyStmt 和 Scope 的子类。
表达式语法 | CodeQL 类 | 超类 | 备注 |
---|---|---|---|
class CNAME «< Expr»? TERM StmtSequence TERM end |
类声明 | Namespace, ConstantWriteAccess | |
module CNAME TERM StmtSequence TERM end |
模块声明 | Namespace, ConstantWriteAccess | |
class << Expr TERM StmtSequence TERM end |
单例类 | 模块基类 |
可调用类¶
本小节中的所有类都是 Callable 的子类。
表达式语法 | CodeQL 类 | 超类 | 备注 |
---|---|---|---|
{ «| «Parameter , »* | »? StmtSequence } |
大括号块 | 块 | |
do «| «Parameter , »* | »? BodyStmt end |
Do块 | Block, BodyStmt | |
-> ( «Parameter , »* ) { StmtSequence } |
Lambda | Callable, BodyStmt | |
-> ( «Parameter , »* ) do BodyStmt end |
Lambda | Callable, BodyStmt | |
def FNAME «Parameter , »* TERM BodyStmt TERM end |
方法 | 方法基类 | |
def self. FNAME «Parameter , »* TERM BodyStmt TERM end |
单例方法 | 方法基类 |
参数类¶
本小节中的所有类都是 Parameter 的子类。
表达式语法 | CodeQL 类 | 超类 | 备注 |
---|---|---|---|
& IDENTIFIER |
块参数 | 命名参数 | |
( «IDENTIFIER , »+ ) |
解构参数 | ||
... |
转发参数 | ||
**nil |
哈希 Splat Nil 参数 | 表示没有关键字参数或关键字模式 | |
** IDENTIFIER |
哈希 Splat 参数 | 命名参数 | |
IDENTIFIER : «Expr»? |
关键字参数 | 命名参数 | |
IDENTIFIER = Expr |
可选参数 | 命名参数 | |
IDENTIFIER | 简单参数 | 命名参数 | |
* IDENTIFIER |
Splat 参数 | 命名参数 |
模式类¶
本小节中的所有类都是 CasePattern 的子类。这些表达式通常出现在 case
使用模式匹配语法时。
表达式语法 | CodeQL 类 | 超类 | 备注 |
---|---|---|---|
CasePattern «| CasePattern»+ |
备用模式 | 案例模式 | |
[ «CasePattern , »* «* IDENTIFIER»? ] |
数组模式 | 案例模式 | |
CasePattern => IDENTIFIER |
As 模式 | 案例模式 | |
[ * «IDENTIFIER»? (, CasePattern)* , * «IDENTIFIER»? ] |
查找模式 | 案例模式 | |
{ «StringlikeLiteral : CasePattern , »* «** IDENTIFIER»? } |
哈希模式 | 案例模式 | |
( CasePattern ) |
带括号的模式 | 案例模式 | |
^ Expr |
引用模式 | 案例模式 |
表达式类¶
本小节中的所有类都是 Expr 的子类。
表达式语法 | CodeQL 类 | 超类 | 备注 |
---|---|---|---|
«Expr , »+ |
参数列表 | Expr | 赋值的右侧或 return 、break 或 next 语句 |
StmtSequence «RescueClause»? «else StmtSequence»? «ensure StmtSequence»? |
BodyStmt | StmtSequence | |
Expr «, Expr»+ |
解构左值表达式 | 左值表达式 | |
Expr | 左值表达式 | Expr | 出现在各种操作左侧的 Expr。可以采用多种形式。 |
Expr : Expr |
对 | Expr | 例如在哈希中或作为关键字参数 |
( StmtSequence ) |
带括号的表达式 | StmtSequence | |
rescue StmtSequence |
救援条款 | Expr | |
Stmt rescue Stmt |
救援修饰符表达式 | Expr | |
StmtSequence TERM Stmt | StmtSequence | Expr | 0 个或多个语句的序列,由分号或换行符分隔 |
StringLiteral StringLiteral | 字符串连接 | Expr | 连续字符串文字的隐式连接 |
变量类¶
本小节中的所有类都是 VariableAccess 的子类。
语法糖和反糖化¶
某些 Ruby 语言特性是常见操作的简写形式,也可以用其他更冗长的形式表达。这类语言特性通常被称为“语法糖”,使程序员更容易编写和阅读代码。这对程序员来说很棒。但是,对于源代码分析器来说,这会导致额外的工作,因为它们需要理解简写符号以及长形式。为了简化分析,CodeQL 会自动对 Ruby 代码进行“反糖化”,有效地将丰富的语法结构重写为使用更简单语法结构的等效代码。
例如,假设 x
是一个具有属性 foo
的对象,则赋值
x.foo = y
将反糖化为类似于以下代码
x.foo=(__synth_0 = y);
__synth_0;
换句话说,实际上是对 x
进行了一个 SetterMethodCall foo=
调用,其参数为 __synth_0 = y
,然后读取 __synth_0
变量。
在 CodeQL 中,这是通过合成对应于此反糖化版本代码的 AstNode 实例来实现的。
请注意,原始的 AssignExpr 和反糖化的 SetterMethodCall 版本都可以在 CodeQL 查询中使用,通常您无需了解可能发生的任何反糖化。但是,如果代码库明确使用 x.foo=(y)
SetterMethodCall 语法,则无法通过搜索 AssignExpr 的实例来找到此语法。
还存在其他合成的 AstNode 实例,有关详细信息,请参阅 isSynthesized 和 getDesugared 谓词。