库文件类介绍,可以分为五类:
- 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是类Method和Constructor的父类,可以用于判断一个元素是否是方法或者构造器。
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,TypeSystemandTypeClass。
例如,找到直接继承Object的nested class:
import java
from NestedClass nc
where nc.getASupertype() instanceof TypeObject
select nc
Generics
Type也有一些子类,用于处理generic types。
GenericType是GenericInterface或者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.getParent和Stmt.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类库提供了两个抽象类:ExprParent和StmtParent,前者表示任何可能成为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