https://github.com/github/codeql/blob/main/docs/ql-style-guide.md
概述Introduction
缩进Indentation
1、每一级缩进使用两个空格
2、必须缩进一个层级的情况
1)模块、类型、类和谓词的整个主体部分需要缩进一级
2)长句被分割时,第二行及后面的行需要缩进一级
3)from、where、select子句跨越多行时,主体部分需要缩进一级
4)量词跨越多行时,主体部分需要缩进一级
/** 模块的主体部分缩进一级 */
module Helpers {
/** 类的主体部分缩进一级 */
class X ... {
/** 谓词的主体部分缩进一级 */
int getNumberOfChildren () {
/** 量词跨越多行时,主体部分缩进一级 */
result = count(int child |
exists(this.getChild(child))
)
}
}
from Call c, string reason
where isDeprecated(c, reason)
/** 长句被分割时,第二行的部分缩进一级 */
select c, "This call to '$@' is deprecated because " + reason + ".",
c.getTarget(), c.getTarget().getName()
文件 - 首选项 - 设置
设置为一个Tab替换为2个空格,然后点击Editor:Detect Indentation,将该选项关闭
换行Line breaks
1、使用UNIX风格的行结尾符
2、每行不超过100个字符
3、长句必须使用换行进行分割,并且将后面的行缩进一个层级,直到整个长句结束
4、需要插入空行的情况
1)在文件的注释和一个import子句之间
2)
3)在一个ql文件中,在开始写from-where-select部分之前
5、避免出现连续的空行
6、cached、pramga、language和bindingset标注结束后必须要另起一行,其他标注后面不需要另起一行。
bindingset[uri]
string int getNamespace(string uri) {
...
}
7、在谓词内部,不应该使用额外的空行
8、另起一行的情况
1)在ql文件中,from、where和select子句结束后必须要另起一行
2)if、then 和else子句结束后必需要另起一行
from Method main
where main.getName() = "Main"
select main, "This is the program entry point."
from Method main
where
main.getName() = "Main" and
main.getNumberOfParameters() = 0
select main, "Main method has no parameters."
if x.isPublic()
then result = "public"
else result = "private"
if
x.isPublic()
then
result = "public"
else
result = "private"
if x.isPublic()
then result = "public"
else
if x.isPrivate()
then result = "private"
else result = "protected"
9、
10、当使用二元操作符的子句跨越多行时,这个二元操作符应该位于前一行的行尾
11、当参数列表需要跨越多行时,必须要在左小括号( 之后进行换行,参数的声明全部放到在下一个缩进级别中,右小括号和左花括号 ) { 不在该缩进级别中。
predicate methodStats(
string qualifiedName, string name, int numberOfParameters,
int numberOfStatements, int numberOfExpressions, int linesOfCode,
int nestingDepth, int numberOfBranches
) {
...
}
花括号Braces
1、花括号遵循 Stroustrup风格,左花括号必须位于前一行的结尾。
2、右花括号必须独占一行,且使用上一层级的缩进;或者与做花括号位于同一行。
class ThrowException extends ThrowExpr {
Foo() {
this.getTarget() instanceof ExceptionClass
}
}
3、主体为空的花括号,左右花括号放在同一行中,并插入一个空格用来间隔左右花括号。
4、不超过最大长度的谓词,应该放在一行中,并且在左花括号后面及右花括号前面各插入一个空格进行间隔。
override string toString() { result = "Throw Exception" }
空格Spaces
1、下面这两种情况必须插入一个空格或者换行
1)=和|的两侧插入空格,或者左侧插入空格,右侧使用换行
2)每个,后面
2、下面这三种情况应该插入一个空格或者换行
1)每个二元操作符的两侧插入空格,或者左侧插入空格,右侧使用换行
2)在范围表达式中时, .. 符号的两侧
3)
3、下面这几种情况不应该插入空格
1)在量词和聚合表达式的后面
2)在调用一个谓词时,谓词名称的后面
3)
4).的两侧
5)在一个范围表达式中,[ 和 ] 的两侧
6)在使用 a.(X) 强制类型转换时
4、除非是在一个缩进中,否则禁止连续使用多个空格,例如为了对齐格式、参数和变量而擅自增加缩进
5、在空白行、行尾禁止插入任何空白字符
6、禁止使用制表符
cached
private predicate foo(Expr e, Expr p) {
exists(int n |
n in [0 .. 1] |
e = p.getChild(n + 1)
)
}
命名Naming
1,如下情景使用大驼峰命名法
1)class的名字
2)module的名字
3)newtype的名字
newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParamNodeEx p)
2,如下情景使用小驼峰命名法
1)谓词的名字
2)变量的名字
3,
4,newtype的名字应该以字母T开头
5,带有返回值的谓词,谓词名应该以字母get开头
6,带有返回值且返回值不唯一的谓词,谓词名应该以字母getA或者getAn开头
7,没有返回值或者参数的谓词,谓词名应该用is或者has开头
8,禁止在名称中使用下划线
9,避免使用短的或者单个字母的名称来命名类、谓词和字段。
10,使用符合目标语言规范的名称
11,使用美式英语
/** ... */
predicate calls(Callable caller, Callable callee) {
...
}
/** ... */
class Bar extends ... {
/** ... */
string getName() { ... }
/** ... */
predicate declares(Member m) { ... }
/** ... */
predicate isGeneric() { ... }
/** ... */
Type getTypeParameter(int n) { ... }
/** ... */
Type getATypeParameter() { ... }
/** Gets the SSA variable ... */
predicate getSsaVariable() { ... }
}