簡體   English   中英

為 Lombok 1.16.8 創建自定義注釋

[英]Create custom annotation for Lombok 1.16.8

我正在編寫一個名為 @PrintedValue 的自定義 Lombok 注釋,它生成方法打印 Hiii。 為此,我創建了如下注釋 class :

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface PrintValue {
    }

然后,我創建了兩個處理程序(javac 和 eclipse 處理程序)。 這是我的代碼:

@ProviderFor(EclipseAnnotationHandler.class) public class HandlePrintValue extends EclipseAnnotationHandler<PrintValue> {
    
    @Override public void handle(AnnotationValues<PrintValue> annotation, Annotation ast, EclipseNode annotationNode) {
        handleFlagUsage(annotationNode, ConfigurationKeys.PRINT_VALUE_FLAG_USAGE, "@PrintValue");
        EclipseHandlerUtil.unboxAndRemoveAnnotationParameter(ast, "onType", "@PrintValue(onType=", annotationNode);
        EclipseNode typeNode = annotationNode.up();
        MethodDeclaration printValMethod = createPrintVal(typeNode, annotationNode, annotationNode.get(), ast);
        injectMethod(typeNode, printValMethod);
        return;
    }
    
    private MethodDeclaration createPrintVal(EclipseNode typeNode, EclipseNode errorNode, ASTNode astNode, Annotation source) {
        TypeDeclaration typeDecl = (TypeDeclaration) typeNode.get();
        
        MethodDeclaration method = new MethodDeclaration(typeDecl.compilationResult);
        setGeneratedBy(method, astNode);
        method.annotations = null;
        method.modifiers = toEclipseModifier(AccessLevel.PUBLIC);
        method.typeParameters = null;
        method.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
        method.selector = "printVal".toCharArray();
        method.arguments = null;
        method.binding = null;
        method.thrownExceptions = null;
        method.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
        
        NameReference systemOutReference = createNameReference("System.out", source);
        Expression[] printlnArguments = new Expression[] {new StringLiteral("Hiiii".toCharArray(), astNode.sourceStart, astNode.sourceEnd, 0)};
        
        MessageSend printlnInvocation = new MessageSend();
        printlnInvocation.arguments = printlnArguments;
        printlnInvocation.receiver = systemOutReference;
        printlnInvocation.selector = "println".toCharArray();
        setGeneratedBy(printlnInvocation, source);
        
        method.bodyStart = method.declarationSourceStart = method.sourceStart = astNode.sourceStart;
        method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = astNode.sourceEnd;
        method.statements = new Statement[] {printlnInvocation};
        return method;
    }
    
}

@ProviderFor(JavacAnnotationHandler.class)
public class HandlePrintValue extends JavacAnnotationHandler<PrintValue> {
    
    @Override
    public void handle(AnnotationValues<PrintValue> annotation, JCAnnotation ast, JavacNode annotationNode) {
        // JavacHandlerUtil.markAnnotationAsProcessed(annotationNode,
        // HelloWorld.class);
        handleFlagUsage(annotationNode, ConfigurationKeys.PRINT_VALUE_FLAG_USAGE, "@PrintValue");
        Context context = annotationNode.getContext();
        Javac8BasedLombokOptions options = Javac8BasedLombokOptions.replaceWithDelombokOptions(context);
        options.deleteLombokAnnotations();
        JavacHandlerUtil.deleteAnnotationIfNeccessary(annotationNode, PrintValue.class);
        JavacHandlerUtil.deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
        JavacNode typeNode = annotationNode.up();
        JCMethodDecl printValMethod = createPrintVal(typeNode);
        
        JavacHandlerUtil.injectMethod(typeNode, printValMethod);
        return;
    }
    
    private JCMethodDecl createPrintVal(JavacNode type) {
        JavacTreeMaker treeMaker = type.getTreeMaker();
        
        JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC);
        List<JCTypeParameter> methodGenericTypes = List.<JCTypeParameter>nil();
        JCExpression methodType = treeMaker.Type(Javac.createVoidType(treeMaker, CTC_VOID));
        Name methodName = type.toName("printVal");
        List<JCVariableDecl> methodParameters = List.<JCVariableDecl>nil();
        List<JCExpression> methodThrows = List.<JCExpression>nil();
        
        JCExpression printlnMethod = JavacHandlerUtil.chainDots(type, "System", "out", "println");
        List<JCExpression> printlnArgs = List.<JCExpression>of(treeMaker.Literal("val"));
        JCMethodInvocation printlnInvocation = treeMaker.Apply(List.<JCExpression>nil(), printlnMethod, printlnArgs);
        JCBlock methodBody = treeMaker.Block(0, List.<JCStatement>of(treeMaker.Exec(printlnInvocation)));
        
        JCExpression defaultValue = null;
        
        return treeMaker.MethodDef(modifiers, methodName, methodType, methodGenericTypes, methodParameters, methodThrows, methodBody, defaultValue);
    }
}

在構建我的項目並將生成的 lombok jar 添加到我的項目后,我可以調用 @PrintValue 注釋,但對於學生 class 未定義 printVal 方法。 導入 lombok.PrintValue;

public @PrintValue class Student {
    private int age;
    private String name;
}

我嘗試啟用注釋處理,但仍然遇到同樣的問題。 如果有人可以幫助我,我將不勝感激。

jdk :8 eclipse 2018-09龍目島1.16.8

添加新的 lombok 注釋的唯一方法是 fork lombok,並且您的注釋類型名 ( @PrintValue )處理程序位於以“lombok.”開頭的 package 中。 其原因很難用簡潔的答案來解釋:它是以下各項的組合:

  • lombok 需要如何集成到 Equinox 引擎中的各種相關模塊(eclipse 運行在其之上的運行時模塊化平台)。
  • Lombok 不想公開任何方法/類型,除了它想要的那些,即 lombok 注釋等等。 特別是,如果 ASM 庫(lombok 在內部使用)是“公開的”,那么在任何也使用 ASM 的項目中使用 lombok 都會變得更加困難。 Lombok 解決了這個問題,但它是您必須分叉創建注釋的部分原因。

當我說“fork lombok”時,我的意思是:

  • 你最終得到一個 jar。 這個 jar 包含 lombok 包含的所有內容,還包含您的 PrintValue 注釋和您的處理程序。
  • It is built by the lombok buildsystem, such that eg your annotation type is a class file in the jar file, but the handler class file ends up as a file entry in the jar with extension .SCL.lombok and not .class .

到目前為止,最簡單的方法是獲取 lombok 源(克隆 git 存儲庫),並在 lombok 擁有它們的同一位置創建您的注釋類型( /src/core/lombok/PrintValue.java ),以及在 lombok 擁有它們的相同位置創建您的處理程序(例如/src/core/lombok/eclipse/handlers/HandlePrintValue.java )。

然后只需ant dist然后java -jar dist/lombok.jar install /path/to/your/eclipse

如果您想為這些創建自己的 lombok 子包,請搜索lombok.extern和 lombok lombok/extern - 特別是在構建文件中(在buildScripts子目錄中); 如果您希望注釋的全名是例如lombok.houria.PrintValue ,您需要告訴 lombok 的構建過程lombok.houria不能得到.SCL.lombok處理,就像lombok.externlomboklombok.experimental don不。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM