import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import java.util.Set;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementScanner9;//10 is not ok
import javax.tools.Diagnostic.Kind;
import javax.annotation.processing.Messager;
@SupportedAnnotationTypes("*")//all annotations
@SupportedSourceVersion(SourceVersion.RELEASE_10)
public class NameCheckProcessor extends AbstractProcessor {
private NameChecker nameChecker;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
this.nameChecker = new NameChecker(processingEnv);
}
//对语法树 每个节点进行检查
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if(!roundEnv.processingOver()){
for(Element e : roundEnv.getRootElements()){
this.nameChecker.checkNames(e);
log(e);//输出是类名
}
}
return false;
}
public static<T> void log(T t){
System.out.println(t);
}
}
class NameChecker{
private final Messager message;
NameCheckScanner nameCheckScanner = new NameCheckScanner();
public NameChecker(ProcessingEnvironment processingEnv) {
this.message = processingEnv.getMessager();
}
/**
* class interface name : camel,first upper method : camel,first upper field
* variable :camel ,first lower const : all upper
*
* @param e
*/
public void checkNames(Element e) {
this.nameCheckScanner.scan(e);
}
private class NameCheckScanner extends ElementScanner9<Void, Void> {
@Override
public Void scan(Element e, Void p) {
return super.scan(e, p);
}
@Override
public Void visitType(TypeElement e, Void p) {
scan(e.getTypeParameters(), p);
log("TypeElement: " + e.getSimpleName(), e);
return super.visitType(e, p);
}
@Override
public Void visitExecutable(ExecutableElement e, Void p) {
if (e.getKind() == ElementKind.METHOD) {
log("ExecutableElement: ", e);
log("ElementKind: " + e.getKind(), e);
log("SimpleName: " + e.getSimpleName(), e);
log("EnclosingElement SimpleName: " + e.getEnclosingElement().getSimpleName(), e);
}
return super.visitExecutable(e, p);
}
@Override
public Void visitVariable(VariableElement e, Void p) {
if (e.getKind() == ElementKind.ENUM_CONSTANT || e.getConstantValue() != null
|| e.getEnclosingElement().getKind() == ElementKind.INTERFACE || e.getKind() == ElementKind.FIELD) {
log("VariableElement:",e);
log("SimpleName: "+e.getSimpleName(),e);
log("kind: "+ e.getKind(),e);
log("EnclosingElement SimpleName: "+ e.getEnclosingElement().getSimpleName(),e);
log("EnclosingElement kind: "+ e.getEnclosingElement().getKind(),e);
log("Modifiers: "+e.getModifiers(),e);
}
return super.visitVariable(e, p);
}
private <T extends CharSequence> void log(T t, Element e) {
message.printMessage(Kind.WARNING, t, e);
}
}
}
public class Badly_Named_Code{
enum A{
red,blue,green;
}
static final int _FORTy_TWO = 42;
public static int NOT_A_CONSTANT = _FORTy_TWO;
protected void Badly_Named_Code(){
return ;
}
public void NOTcameCASEmethodNAME(){
return;
}
}
>javac -processor NameCheckProcessor Badly_Named_Code.java
Badly_Named_Code
Badly_Named_Code.java:1: 警告: TypeElement: Badly_Named_Code
public class Badly_Named_Code{
^
Badly_Named_Code.java:2: 警告: TypeElement: A
enum A{
^
警告: ExecutableElement:
警告: ElementKind: METHOD
警告: SimpleName: values
警告: EnclosingElement SimpleName: A
警告: ExecutableElement:
警告: ElementKind: METHOD
警告: SimpleName: valueOf
警告: EnclosingElement SimpleName: A
Badly_Named_Code.java:3: 警告: VariableElement:
red,blue,green;
^
Badly_Named_Code.java:3: 警告: SimpleName: red
red,blue,green;
^
Badly_Named_Code.java:3: 警告: kind: ENUM_CONSTANT
red,blue,green;
^
Badly_Named_Code.java:3: 警告: EnclosingElement SimpleName: A
red,blue,green;
^
Badly_Named_Code.java:3: 警告: EnclosingElement kind: ENUM
red,blue,green;
^
Badly_Named_Code.java:3: 警告: Modifiers: [public, static, final]
red,blue,green;
^
Badly_Named_Code.java:3: 警告: VariableElement:
red,blue,green;
^
Badly_Named_Code.java:3: 警告: SimpleName: blue
red,blue,green;
^
Badly_Named_Code.java:3: 警告: kind: ENUM_CONSTANT
red,blue,green;
^
Badly_Named_Code.java:3: 警告: EnclosingElement SimpleName: A
red,blue,green;
^
Badly_Named_Code.java:3: 警告: EnclosingElement kind: ENUM
red,blue,green;
^
Badly_Named_Code.java:3: 警告: Modifiers: [public, static, final]
red,blue,green;
^
Badly_Named_Code.java:3: 警告: VariableElement:
red,blue,green;
^
Badly_Named_Code.java:3: 警告: SimpleName: green
red,blue,green;
^
Badly_Named_Code.java:3: 警告: kind: ENUM_CONSTANT
red,blue,green;
^
Badly_Named_Code.java:3: 警告: EnclosingElement SimpleName: A
red,blue,green;
^
Badly_Named_Code.java:3: 警告: EnclosingElement kind: ENUM
red,blue,green;
^
Badly_Named_Code.java:3: 警告: Modifiers: [public, static, final]
red,blue,green;
^
Badly_Named_Code.java:5: 警告: VariableElement:
static final int _FORTy_TWO = 42;
^
Badly_Named_Code.java:5: 警告: SimpleName: _FORTy_TWO
static final int _FORTy_TWO = 42;
^
Badly_Named_Code.java:5: 警告: kind: FIELD
static final int _FORTy_TWO = 42;
^
Badly_Named_Code.java:5: 警告: EnclosingElement SimpleName: Badly_Named_Code
static final int _FORTy_TWO = 42;
^
Badly_Named_Code.java:5: 警告: EnclosingElement kind: CLASS
static final int _FORTy_TWO = 42;
^
Badly_Named_Code.java:5: 警告: Modifiers: [static, final]
static final int _FORTy_TWO = 42;
^
Badly_Named_Code.java:6: 警告: VariableElement:
public static int NOT_A_CONSTANT = _FORTy_TWO;
^
Badly_Named_Code.java:6: 警告: SimpleName: NOT_A_CONSTANT
public static int NOT_A_CONSTANT = _FORTy_TWO;
^
Badly_Named_Code.java:6: 警告: kind: FIELD
public static int NOT_A_CONSTANT = _FORTy_TWO;
^
Badly_Named_Code.java:6: 警告: EnclosingElement SimpleName: Badly_Named_Code
public static int NOT_A_CONSTANT = _FORTy_TWO;
^
Badly_Named_Code.java:6: 警告: EnclosingElement kind: CLASS
public static int NOT_A_CONSTANT = _FORTy_TWO;
^
Badly_Named_Code.java:6: 警告: Modifiers: [public, static]
public static int NOT_A_CONSTANT = _FORTy_TWO;
^
Badly_Named_Code.java:7: 警告: ExecutableElement:
protected void Badly_Named_Code(){
^
Badly_Named_Code.java:7: 警告: ElementKind: METHOD
protected void Badly_Named_Code(){
^
Badly_Named_Code.java:7: 警告: SimpleName: Badly_Named_Code
protected void Badly_Named_Code(){
^
Badly_Named_Code.java:7: 警告: EnclosingElement SimpleName: Badly_Named_Code
protected void Badly_Named_Code(){
^
Badly_Named_Code.java:10: 警告: ExecutableElement:
public void NOTcameCASEmethodNAME(){
^
Badly_Named_Code.java:10: 警告: ElementKind: METHOD
public void NOTcameCASEmethodNAME(){
^
Badly_Named_Code.java:10: 警告: SimpleName: NOTcameCASEmethodNAME
public void NOTcameCASEmethodNAME(){
^
Badly_Named_Code.java:10: 警告: EnclosingElement SimpleName: Badly_Named_Code
public void NOTcameCASEmethodNAME(){
^
48 个警告
涉及的类(不含包名) :
SupportedAnnotationTypes * 支持所有 Annotations
SupportedSourceVersion 支持版本 (唯一,与javac 版本一致,理解的)
AbstractProcessor 继承 (javac -processor 子类)
RoundEnvironment 可以查询有关注释处理的 round 的信息
Element及其子类,TypeElement,VariableElement,ExecutableElement
ElementKind,Kind
Messager 编译的时候可以输出
ElementScanner9 继承 实现一些操作