PS:基于的chechstyle版本 7.3
一、开发maven插件工程
插件代码如下,必须要实现AbstractCheck:
package net.genez.customck.check;
import antlr.collections.AST;
import com.puppycrawl.tools.checkstyle.api.*;
import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
import java.util.ArrayList;
import java.util.List;
/**
* 校验工程内是否有非法的new
* <p>对于反射调用,暂时未实现</p>
*/
public class IllegalNewCheck extends AbstractCheck {
private String pkgName;
private String fileName;
private List<String> unCheckPackage = new ArrayList<String>();
private List<String> illegalClasses = new ArrayList<String>();
private final List<FullIdent> imports = new ArrayList<FullIdent>();
private final List<String> classNames = new ArrayList<>();
private List<DetailAST> newClassList = new ArrayList<DetailAST>();
private int errCount = 0;
/**
* checkstyle配置中的属性设置
* @param names
*/
public void setClasses(String... names) {
for(String name : names){
illegalClasses.add(name);
System.out.println("不允许实例化的类:"+name);
}
}
public void setUnpackage(String... unpackages) {
for(String unpackage : unpackages){
unCheckPackage.add(unpackage);
System.out.println("不需要校验的包:"+unpackage);
}
}
/**
* 本校验器默认接收的ast类型
*/
public int[] getDefaultTokens() {
return new int[] {
TokenTypes.IMPORT,
TokenTypes.LITERAL_NEW,
TokenTypes.PACKAGE_DEF,
TokenTypes.CLASS_DEF,
};
}
/**
* 一个class开始解析
* @param rootAST
*/
@Override
public void beginTree(DetailAST rootAST) {
super.beginTree(rootAST);
pkgName = null;
fileName = null;
imports.clear();
newClassList.clear();
classNames.clear();
FileContents fileContents = getFileContents();
fileName = fileContents.getFileName();
}
/**
* 一个class结束解析
* @param rootAST
*/
@Override
public void finishTree(DetailAST rootAST) {
super.finishTree(rootAST);
//如果当前校验的class在放过的列表中,则不进行校验
if(unCheckPackage.contains(pkgName)){
return;
}
for(DetailAST ast : newClassList){
if(!postProcessLiteralNew(ast)){
errCount++;
}
}
}
@Override
public void destroy() {
super.destroy();
if(errCount>0){
throw new RuntimeException("禁止编译,共有["+errCount+"]个非法远程调用");
}
}
@Override
public void visitToken(DetailAST ast) {
switch (ast.getType()) {
case TokenTypes.LITERAL_NEW:
processLiteralNew(ast);
break;
case TokenTypes.PACKAGE_DEF:
processPackageDef(ast);
break;
case TokenTypes.IMPORT:
processImport(ast);
break;
case TokenTypes.CLASS_DEF:
processClassDef(ast);
break;
default:
throw new IllegalArgumentException("Unknown type " + ast);
}
}
/**
* 执行new关键字的鉴别
* @param ast
*/
private void processLiteralNew(DetailAST ast) {
if (ast.getParent().getType() != TokenType