用于处理 Java 和 Kotlin 程序的抽象语法树类¶
CodeQL 提供了大量用于表示 Java 和 Kotlin 程序抽象语法树的类。
抽象语法树 (AST) 表示程序的语法结构。AST 上的节点表示语句和表达式等元素。
注意
目前 Kotlin 的 CodeQL 分析处于测试阶段。在测试阶段,Kotlin 代码分析以及相应的文档不会像其他语言那样全面。
编写用于 Kotlin 和 Java 分析的 CodeQL 查询¶
通常,您可以使用相同的类来编写用于 Kotlin 和 Java 的查询。您可以使用相同的数据流、污点追踪或 SSA 库,以及相同的类(例如,MethodAccess
或 Class
)来编写这两种语言。当您想要访问特定于 Kotlin 的元素(例如,WhenExpr
)时,则需要使用特定于 Kotlin 的 CodeQL 类。
但是,在某些重要情况下,编写用于 Kotlin 的查询可能会产生与编写用于 Java 的查询相比令人惊讶的结果,因为 CodeQL 使用 Kotlin 源代码的 JVM 字节码表示形式。
当您对 Java 中不存在的代码元素(例如 NotNullExpr (expr!!)
)进行建模时要格外小心,因为它们可能会以意想不到的方式与常见的谓词交互。例如,在以下 Kotlin 代码中,MethodAccess.getQualifier()
返回的是 NotNullExpr
而不是 VarAccess
someVar!!.someMethodCall()
在这种特定情况下,您可以使用谓词 Expr.getUnderlyingExpr()
。这将直接转到底层的 VarAccess
,以产生与 Java 中更相似的行为。
可空元素(?
)也可能会产生意想不到的行为。为了避免出现 NullPointerException
,当 expr
可空时,Kotlin 可能会将 expr.toString()
等调用内联到 String.valueOf(expr)
。请确保您针对提取的代码编写 CodeQL,提取的代码可能与代码库中的代码不完全匹配。
另一个示例是,Kotlin 中的 if-else 表达式在 CodeQL 中被转换为 WhenExprs
,而不是在 Java 中更常见的 IfStmt
。
通常,您可以使用 AST 调试这些问题(您可以使用 Visual Studio Code 的 CodeQL 扩展中的 CodeQL: View AST
命令,或运行 PrintAst.ql
查询),并确切地查看 CodeQL 从您的代码中提取了什么内容。
语句类¶
此表列出了 Stmt 的所有子类。
表达式类¶
有许多表达式类,因此我们按类别进行介绍。本节中的所有类都是 Expr 的子类。
字面量¶
本小节中的所有类都是 Literal 的子类。
表达式语法示例 | CodeQL 类 |
---|---|
true |
BooleanLiteral |
23 |
IntegerLiteral |
23l |
LongLiteral |
4.2f |
FloatingPointLiteral |
4.2 |
DoubleLiteral |
'a' |
CharacterLiteral |
"Hello" |
StringLiteral |
null |
NullLiteral |
一元表达式¶
本小节中的所有类都是 UnaryExpr 的子类。
表达式语法 | CodeQL 类 | 超类 | 备注 |
---|---|---|---|
Expr++ |
PostIncExpr | UnaryAssignExpr | |
Expr-- |
PostDecExpr | UnaryAssignExpr | |
++ Expr |
PreIncExpr | UnaryAssignExpr | |
-- Expr |
PreDecExpr | UnaryAssignExpr | |
~ Expr |
BitNotExpr | BitwiseExpr | 参见下方 BitwiseExpr 的其他子类 |
- Expr |
MinusExpr | ||
+ Expr |
PlusExpr | ||
! Expr |
LogNotExpr | LogicExpr | 参见下方 LogicExpr 的其他子类 |
二元表达式¶
本小节中的所有类都是 BinaryExpr 的子类。
表达式语法 | CodeQL 类 | 超类 |
---|---|---|
Expr * Expr |
MulExpr | |
Expr / Expr |
DivExpr | |
Expr % Expr |
RemExpr | |
Expr + Expr |
AddExpr | |
Expr - Expr |
SubExpr | |
Expr << Expr |
LShiftExpr | |
Expr >> Expr |
RShiftExpr | |
Expr >>> Expr |
URShiftExpr | |
Expr && Expr |
AndLogicalExpr | LogicExpr |
Expr || Expr |
OrLogicalExpr | LogicExpr |
Expr < Expr |
LTExpr | ComparisonExpr |
Expr > Expr |
GTExpr | ComparisonExpr |
Expr <= Expr |
LEExpr | ComparisonExpr |
Expr >= Expr |
GEExpr | ComparisonExpr |
Expr == Expr |
EQExpr | EqualityTest |
Expr != Expr |
NEExpr | EqualityTest |
Expr & Expr |
AndBitwiseExpr | BitwiseExpr |
Expr | Expr |
OrBitwiseExpr | BitwiseExpr |
Expr ^ Expr |
XorBitwiseExpr | BitwiseExpr |
赋值表达式¶
此表中的所有类都是 Assignment 的子类。
表达式语法 | CodeQL 类 | 超类 |
---|---|---|
Expr = Expr |
AssignExpr | |
Expr += Expr |
AssignAddExpr | AssignOp |
Expr -= Expr |
AssignSubExpr | AssignOp |
Expr *= Expr |
AssignMulExpr | AssignOp |
Expr /= Expr |
AssignDivExpr | AssignOp |
Expr %= Expr |
AssignRemExpr | AssignOp |
Expr &= Expr |
AssignAndExpr | AssignOp |
Expr |= Expr |
AssignOrExpr | AssignOp |
Expr ^= Expr |
AssignXorExpr | AssignOp |
Expr <<= Expr |
AssignLShiftExpr | AssignOp |
Expr >>= Expr |
AssignRShiftExpr | AssignOp |
Expr >>>= Expr |
AssignURShiftExpr | AssignOp |
访问¶
表达式语法示例 | CodeQL 类 |
---|---|
this |
ThisAccess |
Outer.this |
|
super |
SuperAccess |
Outer.super |
|
x |
VarAccess |
e.f |
|
a[i] |
ArrayAccess |
f(...) |
MethodAccess |
e.m(...) |
|
String |
TypeAccess |
java.lang.String |
|
? extends Number |
WildcardTypeAccess |
? super Double |
引用字段的 VarAccess 是一个 FieldAccess。
其他¶
表达式语法示例 | CodeQL 类 | 备注 |
---|---|---|
(int) f |
CastExpr | |
o instanceof String |
InstanceOfExpr | |
Expr ? Expr : Expr |
ConditionalExpr | |
String. class |
TypeLiteral | |
new A() |
ClassInstanceExpr | |
new String[3][2] |
ArrayCreationExpr | |
new int[] { 23, 42 } |
||
{ 23, 42 } |
ArrayInit | 只能作为初始化程序出现,或者作为 ArrayCreationExpr 的子项出现。 |
@Annot(key=val) |
Annotation |