深入理解java虚拟机(17):插入式注解处理器实战
实战目标实现一个java命名格式规范检查的插件
类或接口,符合驼峰命名法,首字母大写
方法,符合驼峰命名法,首字母小写
字段:
类或实例变量:符合驼峰命名法,首字母小写
常量:要求全部大写字母或下划线构成,并且第一个字符不能是下划线
给javac编译器添加一个额外的功能,在编译程序时检查程序是否符合以上标准。
代码如下
package org.xiaofeiyang.classloader;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import java.util.Set;
/**
* @author: yangchun
* @description:
* @date: Created in 2019-12-01 21:11
*/
@SupportedAnnotationTypes("*")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class NameCheckProcessor extends AbstractProcessor {
private NameChecker nameChecker;
@Override
public void init(ProcessingEnvironment precessingEnv){
super.init(precessingEnv);
nameChecker = new NameChecker(precessingEnv);
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if(!roundEnv.processingOver()){
for(Element element:roundEnv.getRootElements()){
nameChecker.checkNames(element);
}
}
return false;
}
}
package org.xiaofeiyang.classloader;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.*;
import javax.lang.model.util.ElementScanner6;
import java.util.EnumSet;
import static javax.lang.model.element.ElementKind.*;
import static javax.lang.model.element.Modifier.*;
import static javax.tools.Diagnostic.Kind.WARNING;
/**
* @author: yangchun
* @description:
* @date: Created in 2019-12-01 21:14
*/
public class NameChecker {
private final Messager messager;
NameCheckScanner nameCheckScanner = new NameCheckScanner();
public NameChecker(ProcessingEnvironment precessingEnv) {
this.messager = precessingEnv.getMessager();
}
public void checkNames(Element element) {
nameCheckScanner.scan(element);
}
private class NameCheckScanner extends ElementScanner6<Void,Void>{
@Override
public Void visitType(TypeElement e,Void p){
scan(e.getTypeParameters(),p);
checkCamelCase(e,true);
super.visitType(e,p);
return null;
}
private void checkCamelCase(Element e, boolean b) {
String name = e.getSimpleName().toString();
boolean previousUpper = false;
boolean conventional = true;
int firstCodePoint = name.codePointAt(0);
if(Character.isUpperCase(firstCodePoint)) {
previousUpper = true;
if (!b) {
messager.printMessage(WARNING, "首字母要小写",e);
}
return;
}else if(Character.isLowerCase(firstCodePoint)){
if (b) {
messager.printMessage(WARNING, "首字母要大写",e);
}
return;
}else{
//conventional = false;
int cp = firstCodePoint;
for(int i= Character.charCount(cp);i<name.length();i+=Character.charCount(cp)){
cp = name.codePointAt(i);
if(Character.isUpperCase(cp)){
if(previousUpper){
conventional = false;
break;
}
previousUpper =true;
}else {
previousUpper = false;
}
}
if(!conventional){
messager.printMessage(WARNING, "需要按照驼峰命名法",e);
}
}
}
@Override
public Void visitExecutable(ExecutableElement e, Void p){
if(e.getKind()==METHOD) {
Name name = e.getSimpleName();
//不能与构造函数重名
if(name.contentEquals(e.getEnclosingElement().getSimpleName())){
messager.printMessage(WARNING,"不能与构造函数重名",e);
checkCamelCase(e,false);
}
super.visitExecutable(e, p);
}
return null;
}
@Override
public Void visitVariable(VariableElement e, Void p){
if(e.getKind()==ENUM_CONSTANT||e.getConstantValue()!=null||heuristicallyConstant(e)) {
checkAllCaps(e);
}else{
checkCamelCase(e,false);
}
return null;
}
private void checkAllCaps(VariableElement e) {
String name = e.getSimpleName().toString();
boolean conventional = true;
int firstCodePoint = name.codePointAt(0);
if(!Character.isUpperCase(firstCodePoint)) {
conventional = false;
}else{
boolean previousUppercore = false;
int cp = firstCodePoint;
for(int i= Character.charCount(cp);i<name.length();i+=Character.charCount(cp)){
cp = name.codePointAt(i);
if(cp==(int)'_'){
if(previousUppercore){
conventional = false;
break;
}
previousUppercore =true;
}else {
previousUppercore = false;
if(!Character.isUpperCase(cp)&&!Character.isDigit(cp)){
conventional =false;
break;
}
}
}
if(!conventional){
messager.printMessage(WARNING, "常量需要以大写字母或者下划线命名,并且以字母开头",e);
}
}
}
//判断变量是否是常量
private boolean heuristicallyConstant(VariableElement e) {
if(e.getEnclosingElement().getKind()==INTERFACE) {
return true;
}else if(e.getKind()==FIELD&&e.getModifiers().containsAll(EnumSet.of(PUBLIC,STATIC,FINAL))){
return true;
}else {
return false;
}
}
}
}
浙公网安备 33010602011771号