Search in sources :

Example 11 with JavacNode

use of lombok.javac.JavacNode in project lombok by rzwitserloot.

the class HandleHelper method handle.

@Override
public void handle(AnnotationValues<Helper> annotation, JCAnnotation ast, JavacNode annotationNode) {
    handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.HELPER_FLAG_USAGE, "@Helper");
    deleteAnnotationIfNeccessary(annotationNode, Helper.class);
    JavacNode annotatedType = annotationNode.up();
    JavacNode containingBlock = annotatedType == null ? null : annotatedType.directUp();
    List<JCStatement> origStatements = getStatementsFromJcNode(containingBlock == null ? null : containingBlock.get());
    if (annotatedType == null || annotatedType.getKind() != Kind.TYPE || origStatements == null) {
        annotationNode.addError("@Helper is legal only on method-local classes.");
        return;
    }
    JCClassDecl annotatedType_ = (JCClassDecl) annotatedType.get();
    Iterator<JCStatement> it = origStatements.iterator();
    while (it.hasNext()) {
        if (it.next() == annotatedType_) {
            break;
        }
    }
    java.util.List<String> knownMethodNames = new ArrayList<String>();
    for (JavacNode ch : annotatedType.down()) {
        if (ch.getKind() != Kind.METHOD)
            continue;
        String n = ch.getName();
        if (n == null || n.isEmpty() || n.charAt(0) == '<')
            continue;
        knownMethodNames.add(n);
    }
    Collections.sort(knownMethodNames);
    final String[] knownMethodNames_ = knownMethodNames.toArray(new String[knownMethodNames.size()]);
    final Name helperName = annotationNode.toName("$" + annotatedType_.name);
    final boolean[] helperUsed = new boolean[1];
    final JavacTreeMaker maker = annotationNode.getTreeMaker();
    TreeVisitor<Void, Void> visitor = new TreeScanner<Void, Void>() {

        @Override
        public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
            JCMethodInvocation jcmi = (JCMethodInvocation) node;
            apply(jcmi);
            return super.visitMethodInvocation(node, p);
        }

        private void apply(JCMethodInvocation jcmi) {
            if (!(jcmi.meth instanceof JCIdent))
                return;
            JCIdent jci = (JCIdent) jcmi.meth;
            if (Arrays.binarySearch(knownMethodNames_, jci.name.toString()) < 0)
                return;
            jcmi.meth = maker.Select(maker.Ident(helperName), jci.name);
            helperUsed[0] = true;
        }
    };
    while (it.hasNext()) {
        JCStatement stat = it.next();
        stat.accept(visitor, null);
    }
    if (!helperUsed[0]) {
        annotationNode.addWarning("No methods of this helper class are ever used.");
        return;
    }
    ListBuffer<JCStatement> newStatements = new ListBuffer<JCStatement>();
    boolean mark = false;
    for (JCStatement stat : origStatements) {
        newStatements.append(stat);
        if (mark || stat != annotatedType_)
            continue;
        mark = true;
        JCExpression init = maker.NewClass(null, List.<JCExpression>nil(), maker.Ident(annotatedType_.name), List.<JCExpression>nil(), null);
        JCExpression varType = maker.Ident(annotatedType_.name);
        JCVariableDecl decl = maker.VarDef(maker.Modifiers(Flags.FINAL), helperName, varType, init);
        newStatements.append(decl);
    }
    setStatementsOfJcNode(containingBlock.get(), newStatements.toList());
}
Also used : JCClassDecl(com.sun.tools.javac.tree.JCTree.JCClassDecl) JCIdent(com.sun.tools.javac.tree.JCTree.JCIdent) JavacTreeMaker(lombok.javac.JavacTreeMaker) ListBuffer(com.sun.tools.javac.util.ListBuffer) ArrayList(java.util.ArrayList) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Name(com.sun.tools.javac.util.Name) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JavacNode(lombok.javac.JavacNode) TreeScanner(com.sun.source.util.TreeScanner) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree)

Example 12 with JavacNode

use of lombok.javac.JavacNode in project lombok by rzwitserloot.

the class HandleLog method processAnnotation.

public static void processAnnotation(LoggingFramework framework, AnnotationValues<?> annotation, JavacNode annotationNode, String loggerTopic) {
    deleteAnnotationIfNeccessary(annotationNode, framework.getAnnotationClass());
    JavacNode typeNode = annotationNode.up();
    switch(typeNode.getKind()) {
        case TYPE:
            String logFieldName = annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_NAME);
            if (logFieldName == null)
                logFieldName = "log";
            boolean useStatic = !Boolean.FALSE.equals(annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_IS_STATIC));
            if ((((JCClassDecl) typeNode.get()).mods.flags & Flags.INTERFACE) != 0) {
                annotationNode.addError("@Log is legal only on classes and enums.");
                return;
            }
            if (fieldExists(logFieldName, typeNode) != MemberExistsResult.NOT_EXISTS) {
                annotationNode.addWarning("Field '" + logFieldName + "' already exists.");
                return;
            }
            JCFieldAccess loggingType = selfType(typeNode);
            createField(framework, typeNode, loggingType, annotationNode.get(), logFieldName, useStatic, loggerTopic);
            break;
        default:
            annotationNode.addError("@Log is legal only on types.");
            break;
    }
}
Also used : JCClassDecl(com.sun.tools.javac.tree.JCTree.JCClassDecl) JavacNode(lombok.javac.JavacNode) JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess)

Example 13 with JavacNode

use of lombok.javac.JavacNode in project lombok by rzwitserloot.

the class HandleSetter method generateSetterForType.

public void generateSetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelSetter) {
    if (checkForTypeLevelSetter) {
        if (hasAnnotation(Setter.class, typeNode)) {
            //The annotation will make it happen, so we can skip it.
            return;
        }
    }
    JCClassDecl typeDecl = null;
    if (typeNode.get() instanceof JCClassDecl)
        typeDecl = (JCClassDecl) typeNode.get();
    long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags;
    boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0;
    if (typeDecl == null || notAClass) {
        errorNode.addError("@Setter is only supported on a class or a field.");
        return;
    }
    for (JavacNode field : typeNode.down()) {
        if (field.getKind() != Kind.FIELD)
            continue;
        JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
        //Skip fields that start with $
        if (fieldDecl.name.toString().startsWith("$"))
            continue;
        //Skip static fields.
        if ((fieldDecl.mods.flags & Flags.STATIC) != 0)
            continue;
        //Skip final fields.
        if ((fieldDecl.mods.flags & Flags.FINAL) != 0)
            continue;
        generateSetterForField(field, errorNode, level);
    }
}
Also used : JCClassDecl(com.sun.tools.javac.tree.JCTree.JCClassDecl) JavacNode(lombok.javac.JavacNode) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl)

Example 14 with JavacNode

use of lombok.javac.JavacNode in project lombok by rzwitserloot.

the class HandleSneakyThrows method handleMethod.

public void handleMethod(JavacNode annotation, JCMethodDecl method, Collection<String> exceptions) {
    JavacNode methodNode = annotation.up();
    if ((method.mods.flags & Flags.ABSTRACT) != 0) {
        annotation.addError("@SneakyThrows can only be used on concrete methods.");
        return;
    }
    if (method.body == null || method.body.stats.isEmpty()) {
        generateEmptyBlockWarning(methodNode, annotation, false);
        return;
    }
    final JCStatement constructorCall = method.body.stats.get(0);
    final boolean isConstructorCall = isConstructorCall(constructorCall);
    List<JCStatement> contents = isConstructorCall ? method.body.stats.tail : method.body.stats;
    if (contents == null || contents.isEmpty()) {
        generateEmptyBlockWarning(methodNode, annotation, true);
        return;
    }
    for (String exception : exceptions) {
        contents = List.of(buildTryCatchBlock(methodNode, contents, exception, annotation.get()));
    }
    method.body.stats = isConstructorCall ? List.of(constructorCall).appendList(contents) : contents;
    methodNode.rebuild();
}
Also used : JavacNode(lombok.javac.JavacNode) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement)

Example 15 with JavacNode

use of lombok.javac.JavacNode in project lombok by rzwitserloot.

the class HandleSneakyThrows method handle.

@Override
public void handle(AnnotationValues<SneakyThrows> annotation, JCAnnotation ast, JavacNode annotationNode) {
    handleFlagUsage(annotationNode, ConfigurationKeys.SNEAKY_THROWS_FLAG_USAGE, "@SneakyThrows");
    deleteAnnotationIfNeccessary(annotationNode, SneakyThrows.class);
    Collection<String> exceptionNames = annotation.getRawExpressions("value");
    if (exceptionNames.isEmpty()) {
        exceptionNames = Collections.singleton("java.lang.Throwable");
    }
    java.util.List<String> exceptions = new ArrayList<String>();
    for (String exception : exceptionNames) {
        if (exception.endsWith(".class"))
            exception = exception.substring(0, exception.length() - 6);
        exceptions.add(exception);
    }
    JavacNode owner = annotationNode.up();
    switch(owner.getKind()) {
        case METHOD:
            handleMethod(annotationNode, (JCMethodDecl) owner.get(), exceptions);
            break;
        default:
            annotationNode.addError("@SneakyThrows is legal only on methods and constructors.");
            break;
    }
}
Also used : JavacNode(lombok.javac.JavacNode) ArrayList(java.util.ArrayList)

Aggregations

JavacNode (lombok.javac.JavacNode)52 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)27 JCClassDecl (com.sun.tools.javac.tree.JCTree.JCClassDecl)23 ListBuffer (com.sun.tools.javac.util.ListBuffer)18 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)15 JavacTreeMaker (lombok.javac.JavacTreeMaker)15 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)13 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)13 Name (com.sun.tools.javac.util.Name)11 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)9 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)8 JCModifiers (com.sun.tools.javac.tree.JCTree.JCModifiers)7 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)6 ArrayList (java.util.ArrayList)6 JCMethodInvocation (com.sun.tools.javac.tree.JCTree.JCMethodInvocation)5 JCTree (com.sun.tools.javac.tree.JCTree)4 JCArrayTypeTree (com.sun.tools.javac.tree.JCTree.JCArrayTypeTree)4 JCFieldAccess (com.sun.tools.javac.tree.JCTree.JCFieldAccess)4 JCPrimitiveTypeTree (com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree)4 AccessLevel (lombok.AccessLevel)4