[Learning CodeQL] [CodeQL for Java][CodeQL library for Java]

库文件类介绍,可以分为五类:

  • Classes for representing program elements (such as classes and methods)
  • Classes for representing AST nodes (such as statements and expressions)
  • Classes for representing metadata (such as annotations and comments)
  • Classes for computing metrics (such as cyclomatic complexity and coupling)
  • Classes for navigating the program’s call graph

Program elements

这些类表示命名的程序元素,比如包 (Package), 编译单元 (CompilationUnit), 类型 (Type), 方法 (Method), 构造器 (Constructor), 和变量 (Variable).
这些类型的父类是Element,这个类提供了通用的predicates:获取元素名以及判断两个元素是否nested inside each other。
Callable是类MethodConstructor的父类,可以用于判断一个元素是否是方法或者构造器。

Types

Type有很多子类型,包括:

  • PrimitiveType(基本数据类型):包括boolean, byte, char, double, float, int, long, short,void,<nulltype>
  • RefType(引用数据类型),它有如下几个子类:
  • Class:表示java的类
  • Interface:表示java的接口
  • EnumType:表示java的枚举类型
  • Array:表示java的array类型
    例如,查找代码中的所有int类型
import java

from Variable v, PrimitiveType pt
where pt = v.getType() and
    pt.hasName("int")
select v

引用数据类型也可以根据声明的范围分为两类:

  • TopLevelType:在编译单元中定义为top-level的引用数据类型
  • NestedType:在其他类型内部定义的引用数据类型
    例如,查找top-level类型的名字与编译单元的名字不同的:
import java

from TopLevelType tl
where tl.getName() != tl.getCompilationUnit().getName()
select tl

更加具体的,还可以定义

  • TopLevelClass:在编译单元中定义的top-level的类
  • NestedClass:在其他类型内部定义的类:比如,LocalClass,在方法或者构造器内定义的类;AnonymousClass匿名类。
    同时,也定义了java中的单例类,它们与java中的含义类似:TypeObject, TypeCloneable, TypeRuntime, TypeSerializable, TypeString, TypeSystem and TypeClass
    例如,找到直接继承Object的nested class:
import java

from NestedClass nc
where nc.getASupertype() instanceof TypeObject
select nc
Generics

Type也有一些子类,用于处理generic types。
GenericTypeGenericInterface或者GenericClass
例如,查找所有使用了map泛型的地方:

import java

from GenericInterface map, ParameterizedType pt
where map.hasQualifiedName("java.util", "Map") and
    pt.getSourceDeclaration() = map
select pt

Variables

Variable表示java类中的变量,比如类中的成员属性(static或者其他类型),本地变量,或者参数。
与此相对,有三个子类:

  • Field表示java中的成员属性。
  • LocalVariableDecl表示本地变量。
  • Parameter表示方法或者构造器的参数。

Abstract syntax tree

这个分类中的类表示抽象语法树(AST)的节点,也就是statements(Stmt类)和expressions(Expr类)。
Stmt类和Expr类有一些成员谓词:

  • Expr.getAChildExpr返回指定的expression的子expression.
  • Stmt.getAChild返回直接在指定statement内部的statement或者expression.
  • Expr.getParentStmt.getParent返回AST节点的父节点。

例如,找到所有父节点为return语句的expression:

import java

from Expr e
where e.getParent() instanceof ReturnStmt
select e

例如,找到所有父节点为if表达式的statement:

import java

from Stmt s
where s.getParent() instanceof IfStmt
select s

例如,找到所有method体:

import java

from Stmt s
where s.getParent() instanceof Method
select s

根据上面的例子,可以得到:
一个expression的父节点可能不是expression,它可能是statement,比如IfStmt。与此类似,一个statement的父节点不一定是statement,它可能是一个方法或者构造器。因此,QL java类库提供了两个抽象类:ExprParentStmtParent,前者表示任何可能成为expression父节点的节点,后者表示任何可能成为statement父节点的节点。

Metadata

包括[annotations]注解和[Javadoc]注释。
Annotatable是程序中可以被注解的程序元素的父类。这些可以被注解的程序元素包括:包、引用类型、成员属性、方法、构造器,局部变量声明等。针对这些元素,谓词getAnAnnotation可以获取这些谓词的注解。
例如,获取所有构造器的注解:

import java

from Constructor c
select c.getAnAnnotation()

例如,获取构造器类型为“Deprecated”的注解:

import java

from Constructor c, Annotation ann, AnnotationType anntp
where ann = c.getAnAnnotation() and
    anntp = ann.getType() and
    anntp.hasQualifiedName("java.lang", "Deprecated")
select ann

针对JavaDoc,类Element有一个成员谓词getDoc,返回一个委派的Documentable对象。
例如,找到所有私有属性上的javadoc注释:

import java

from Field f, Javadoc jdoc
where f.isPrivate() and
    jdoc = f.getDoc().getJavadoc()
select jdoc

例如,找到所有私有属性上的javadoc注释并且含有作者标签。

import java

from Field f, Javadoc jdoc, AuthorTag at
where f.isPrivate() and
    jdoc = f.getDoc().getJavadoc() and
    at.getParent+() = jdoc
select at

其中,“getParent+”表示任意深度的,都会返回。

Metrics

metrics相关的并非使用成员谓词,而是使用delegate类来实现的。
包括六个类:MetricElement, MetricPackage, MetricRefType, MetricField, MetricCallable, MetricStmt.
比如,返回所有圈复杂度大于40的方法:

import java

from Method m, MetricCallable mc
where mc = m.getMetrics() and
    mc.getCyclomaticComplexity() > 40
select m

Call Graph

Callable类包括方法和构造函数。
例如,找到所有调用println方法的地方:

import java

from Call c, Method m
where m = c.getCallee() and
    m.hasName("println")
select c

找到从未被调用的构造器和方法:

import java

from Callable c
where not exists(c.getAReference())
select c

Reference

https://help.semmle.com/QL/learn-ql/java/introduce-libraries-java.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349