https://github.com/github/codeql/blob/main/docs/ql-style-guide.md

概述Introduction

缩进Indentation

1、每一级缩进使用两个空格
2、必须缩进一个层级的情况
1)模块、类型、类和谓词的整个主体部分需要缩进一级
2)长句被分割时,第二行及后面的行需要缩进一级
3)from、where、select子句跨越多行时,主体部分需要缩进一级
4)量词跨越多行时,主体部分需要缩进一级

  1. /** 模块的主体部分缩进一级 */
  2. module Helpers {
  3. /** 类的主体部分缩进一级 */
  4. class X ... {
  5. /** 谓词的主体部分缩进一级 */
  6. int getNumberOfChildren () {
  7. /** 量词跨越多行时,主体部分缩进一级 */
  8. result = count(int child |
  9. exists(this.getChild(child))
  10. )
  11. }
  12. }
  1. from Call c, string reason
  2. where isDeprecated(c, reason)
  3. /** 长句被分割时,第二行的部分缩进一级 */
  4. select c, "This call to '$@' is deprecated because " + reason + ".",
  5. c.getTarget(), c.getTarget().getName()

文件 - 首选项 - 设置
设置为一个Tab替换为2个空格,然后点击Editor:Detect Indentation,将该选项关闭
image.png

换行Line breaks

1、使用UNIX风格的行结尾符
2、每行不超过100个字符
3、长句必须使用换行进行分割,并且将后面的行缩进一个层级,直到整个长句结束
4、需要插入空行的情况
1)在文件的注释和一个import子句之间
2)
3)在一个ql文件中,在开始写from-where-select部分之前
5、避免出现连续的空行
6、cached、pramga、language和bindingset标注结束后必须要另起一行,其他标注后面不需要另起一行。

  1. bindingset[uri]
  2. string int getNamespace(string uri) {
  3. ...
  4. }

7、在谓词内部,不应该使用额外的空行
8、另起一行的情况
1)在ql文件中,from、where和select子句结束后必须要另起一行
2)if、then 和else子句结束后必需要另起一行

  1. from Method main
  2. where main.getName() = "Main"
  3. select main, "This is the program entry point."
  1. from Method main
  2. where
  3. main.getName() = "Main" and
  4. main.getNumberOfParameters() = 0
  5. select main, "Main method has no parameters."
  1. if x.isPublic()
  2. then result = "public"
  3. else result = "private"
  1. if
  2. x.isPublic()
  3. then
  4. result = "public"
  5. else
  6. result = "private"
  1. if x.isPublic()
  2. then result = "public"
  3. else
  4. if x.isPrivate()
  5. then result = "private"
  6. else result = "protected"

9、
10、当使用二元操作符的子句跨越多行时,这个二元操作符应该位于前一行的行尾
11、当参数列表需要跨越多行时,必须要在左小括号( 之后进行换行,参数的声明全部放到在下一个缩进级别中,右小括号和左花括号 ) { 不在该缩进级别中。

  1. predicate methodStats(
  2. string qualifiedName, string name, int numberOfParameters,
  3. int numberOfStatements, int numberOfExpressions, int linesOfCode,
  4. int nestingDepth, int numberOfBranches
  5. ) {
  6. ...
  7. }

花括号Braces

1、花括号遵循 Stroustrup风格,左花括号必须位于前一行的结尾。
2、右花括号必须独占一行,且使用上一层级的缩进;或者与做花括号位于同一行。

  1. class ThrowException extends ThrowExpr {
  2. Foo() {
  3. this.getTarget() instanceof ExceptionClass
  4. }
  5. }

3、主体为空的花括号,左右花括号放在同一行中,并插入一个空格用来间隔左右花括号。
4、不超过最大长度的谓词,应该放在一行中,并且在左花括号后面及右花括号前面各插入一个空格进行间隔。

  1. 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、禁止使用制表符

  1. cached
  2. private predicate foo(Expr e, Expr p) {
  3. exists(int n |
  4. n in [0 .. 1] |
  5. e = p.getChild(n + 1)
  6. )
  7. }

命名Naming

1,如下情景使用大驼峰命名法
1)class的名字
2)module的名字
3)newtype的名字

  1. newtype TSummaryCtx1 =
  2. TSummaryCtx1None() or
  3. TSummaryCtx1Param(ParamNodeEx p)

2,如下情景使用小驼峰命名法
1)谓词的名字
2)变量的名字
3,
4,newtype的名字应该以字母T开头
5,带有返回值的谓词,谓词名应该以字母get开头
6,带有返回值且返回值不唯一的谓词,谓词名应该以字母getA或者getAn开头
7,没有返回值或者参数的谓词,谓词名应该用is或者has开头
8,禁止在名称中使用下划线
9,避免使用短的或者单个字母的名称来命名类、谓词和字段。
10,使用符合目标语言规范的名称
11,使用美式英语

  1. /** ... */
  2. predicate calls(Callable caller, Callable callee) {
  3. ...
  4. }
  1. /** ... */
  2. class Bar extends ... {
  3. /** ... */
  4. string getName() { ... }
  5. /** ... */
  6. predicate declares(Member m) { ... }
  7. /** ... */
  8. predicate isGeneric() { ... }
  9. /** ... */
  10. Type getTypeParameter(int n) { ... }
  11. /** ... */
  12. Type getATypeParameter() { ... }
  13. /** Gets the SSA variable ... */
  14. predicate getSsaVariable() { ... }
  15. }

文档Documentation

公式Formulas

术语Glossary