Search in sources :

Example 11 with JavacTreeMaker

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

the class HandleEqualsAndHashCode method createHashCode.

public JCMethodDecl createHashCode(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, JCTree source) {
    JavacTreeMaker maker = typeNode.getTreeMaker();
    JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(typeNode, "Override"), List.<JCExpression>nil());
    JCModifiers mods = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation));
    JCExpression returnType = maker.TypeIdent(CTC_INT);
    ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
    Name primeName = typeNode.toName(PRIME_NAME);
    Name resultName = typeNode.toName(RESULT_NAME);
    long finalFlag = JavacHandlerUtil.addFinalIfNeeded(0L, typeNode.getContext());
    /* final int PRIME = X; */
    {
        if (!fields.isEmpty() || callSuper) {
            statements.append(maker.VarDef(maker.Modifiers(finalFlag), primeName, maker.TypeIdent(CTC_INT), maker.Literal(HandlerUtil.primeForHashcode())));
        }
    }
    /* int result = 1; */
    {
        statements.append(maker.VarDef(maker.Modifiers(0), resultName, maker.TypeIdent(CTC_INT), maker.Literal(1)));
    }
    if (callSuper) {
        JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("hashCode")), List.<JCExpression>nil());
        statements.append(createResultCalculation(typeNode, callToSuper));
    }
    Name dollar = typeNode.toName("$");
    for (JavacNode fieldNode : fields) {
        JCExpression fType = getFieldType(fieldNode, fieldAccess);
        JCExpression fieldAccessor = createFieldAccessor(maker, fieldNode, fieldAccess);
        if (fType instanceof JCPrimitiveTypeTree) {
            switch(((JCPrimitiveTypeTree) fType).getPrimitiveTypeKind()) {
                case BOOLEAN:
                    /* this.fieldName ? X : Y */
                    statements.append(createResultCalculation(typeNode, maker.Parens(maker.Conditional(fieldAccessor, maker.Literal(HandlerUtil.primeForTrue()), maker.Literal(HandlerUtil.primeForFalse())))));
                    break;
                case LONG:
                    {
                        Name dollarFieldName = dollar.append(((JCVariableDecl) fieldNode.get()).name);
                        statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, maker.TypeIdent(CTC_LONG), fieldAccessor));
                        statements.append(createResultCalculation(typeNode, longToIntForHashCode(maker, maker.Ident(dollarFieldName), maker.Ident(dollarFieldName))));
                    }
                    break;
                case FLOAT:
                    /* Float.floatToIntBits(this.fieldName) */
                    statements.append(createResultCalculation(typeNode, maker.Apply(List.<JCExpression>nil(), genJavaLangTypeRef(typeNode, "Float", "floatToIntBits"), List.of(fieldAccessor))));
                    break;
                case DOUBLE:
                    {
                        /* longToIntForHashCode(Double.doubleToLongBits(this.fieldName)) */
                        Name dollarFieldName = dollar.append(((JCVariableDecl) fieldNode.get()).name);
                        JCExpression init = maker.Apply(List.<JCExpression>nil(), genJavaLangTypeRef(typeNode, "Double", "doubleToLongBits"), List.of(fieldAccessor));
                        statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, maker.TypeIdent(CTC_LONG), init));
                        statements.append(createResultCalculation(typeNode, longToIntForHashCode(maker, maker.Ident(dollarFieldName), maker.Ident(dollarFieldName))));
                    }
                    break;
                default:
                case BYTE:
                case SHORT:
                case INT:
                case CHAR:
                    /* just the field */
                    statements.append(createResultCalculation(typeNode, fieldAccessor));
                    break;
            }
        } else if (fType instanceof JCArrayTypeTree) {
            /* java.util.Arrays.deepHashCode(this.fieldName) //use just hashCode() for primitive arrays. */
            boolean multiDim = ((JCArrayTypeTree) fType).elemtype instanceof JCArrayTypeTree;
            boolean primitiveArray = ((JCArrayTypeTree) fType).elemtype instanceof JCPrimitiveTypeTree;
            boolean useDeepHC = multiDim || !primitiveArray;
            JCExpression hcMethod = chainDots(typeNode, "java", "util", "Arrays", useDeepHC ? "deepHashCode" : "hashCode");
            statements.append(createResultCalculation(typeNode, maker.Apply(List.<JCExpression>nil(), hcMethod, List.of(fieldAccessor))));
        } else /* objects */
        {
            /* final java.lang.Object $fieldName = this.fieldName; */
            /* ($fieldName == null ? NULL_PRIME : $fieldName.hashCode()) */
            Name dollarFieldName = dollar.append(((JCVariableDecl) fieldNode.get()).name);
            statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, genJavaLangTypeRef(typeNode, "Object"), fieldAccessor));
            JCExpression hcCall = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(dollarFieldName), typeNode.toName("hashCode")), List.<JCExpression>nil());
            JCExpression thisEqualsNull = maker.Binary(CTC_EQUAL, maker.Ident(dollarFieldName), maker.Literal(CTC_BOT, null));
            statements.append(createResultCalculation(typeNode, maker.Parens(maker.Conditional(thisEqualsNull, maker.Literal(HandlerUtil.primeForNull()), hcCall))));
        }
    }
    /* return result; */
    {
        statements.append(maker.Return(maker.Ident(resultName)));
    }
    JCBlock body = maker.Block(0, statements.toList());
    return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("hashCode"), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null), source, typeNode.getContext());
}
Also used : JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JavacTreeMaker(lombok.javac.JavacTreeMaker) ListBuffer(com.sun.tools.javac.util.ListBuffer) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Name(com.sun.tools.javac.util.Name) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JavacNode(lombok.javac.JavacNode) JCModifiers(com.sun.tools.javac.tree.JCTree.JCModifiers) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation) JCArrayTypeTree(com.sun.tools.javac.tree.JCTree.JCArrayTypeTree)

Example 12 with JavacTreeMaker

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

the class HandleEqualsAndHashCode method createCanEqual.

public JCMethodDecl createCanEqual(JavacNode typeNode, JCTree source, List<JCAnnotation> onParam) {
    /* protected boolean canEqual(final java.lang.Object other) {
		 *     return other instanceof Outer.Inner.MyType;
		 * }
		 */
    JavacTreeMaker maker = typeNode.getTreeMaker();
    JCModifiers mods = maker.Modifiers(Flags.PROTECTED, List.<JCAnnotation>nil());
    JCExpression returnType = maker.TypeIdent(CTC_BOOLEAN);
    Name canEqualName = typeNode.toName("canEqual");
    JCExpression objectType = genJavaLangTypeRef(typeNode, "Object");
    Name otherName = typeNode.toName("other");
    long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
    List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(flags, onParam), otherName, objectType, null));
    JCBlock body = maker.Block(0, List.<JCStatement>of(maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode, false)))));
    return recursiveSetGeneratedBy(maker.MethodDef(mods, canEqualName, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source, typeNode.getContext());
}
Also used : JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JavacTreeMaker(lombok.javac.JavacTreeMaker) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCModifiers(com.sun.tools.javac.tree.JCTree.JCModifiers) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Name(com.sun.tools.javac.util.Name)

Example 13 with JavacTreeMaker

use of lombok.javac.JavacTreeMaker 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 14 with JavacTreeMaker

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

the class HandleLog method createField.

private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source, String logFieldName, boolean useStatic, String loggerTopic) {
    JavacTreeMaker maker = typeNode.getTreeMaker();
    // private static final <loggerType> log = <factoryMethod>(<parameter>);
    JCExpression loggerType = chainDotsString(typeNode, framework.getLoggerTypeName());
    JCExpression factoryMethod = chainDotsString(typeNode, framework.getLoggerFactoryMethodName());
    JCExpression loggerName;
    if (loggerTopic == null || loggerTopic.trim().length() == 0) {
        loggerName = framework.createFactoryParameter(typeNode, loggingType);
    } else {
        loggerName = maker.Literal(loggerTopic);
    }
    JCMethodInvocation factoryMethodCall = maker.Apply(List.<JCExpression>nil(), factoryMethod, List.<JCExpression>of(loggerName));
    JCVariableDecl fieldDecl = recursiveSetGeneratedBy(maker.VarDef(maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (useStatic ? Flags.STATIC : 0)), typeNode.toName(logFieldName), loggerType, factoryMethodCall), source, typeNode.getContext());
    injectFieldAndMarkGenerated(typeNode, fieldDecl);
    return true;
}
Also used : JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JavacTreeMaker(lombok.javac.JavacTreeMaker) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl)

Example 15 with JavacTreeMaker

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

the class HandleSneakyThrows method buildTryCatchBlock.

public JCStatement buildTryCatchBlock(JavacNode node, List<JCStatement> contents, String exception, JCTree source) {
    JavacTreeMaker maker = node.getTreeMaker();
    Context context = node.getContext();
    JCBlock tryBlock = setGeneratedBy(maker.Block(0, contents), source, context);
    JCExpression varType = chainDots(node, exception.split("\\."));
    JCVariableDecl catchParam = maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER), node.toName("$ex"), varType, null);
    JCExpression lombokLombokSneakyThrowNameRef = chainDots(node, "lombok", "Lombok", "sneakyThrow");
    JCBlock catchBody = maker.Block(0, List.<JCStatement>of(maker.Throw(maker.Apply(List.<JCExpression>nil(), lombokLombokSneakyThrowNameRef, List.<JCExpression>of(maker.Ident(node.toName("$ex")))))));
    JCTry tryStatement = maker.Try(tryBlock, List.of(recursiveSetGeneratedBy(maker.Catch(catchParam, catchBody), source, context)), null);
    if (JavacHandlerUtil.inNetbeansEditor(node)) {
        //set span (start and end position) of the try statement and the main block
        //this allows NetBeans to dive into the statement correctly:
        JCCompilationUnit top = (JCCompilationUnit) node.top().get();
        int startPos = contents.head.pos;
        int endPos = Javac.getEndPosition(contents.last().pos(), top);
        tryBlock.pos = startPos;
        tryStatement.pos = startPos;
        Javac.storeEnd(tryBlock, endPos, top);
        Javac.storeEnd(tryStatement, endPos, top);
    }
    return setGeneratedBy(tryStatement, source, context);
}
Also used : Context(com.sun.tools.javac.util.Context) JCTry(com.sun.tools.javac.tree.JCTree.JCTry) JCCompilationUnit(com.sun.tools.javac.tree.JCTree.JCCompilationUnit) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JavacTreeMaker(lombok.javac.JavacTreeMaker) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl)

Aggregations

JavacTreeMaker (lombok.javac.JavacTreeMaker)39 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)33 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)18 ListBuffer (com.sun.tools.javac.util.ListBuffer)17 Name (com.sun.tools.javac.util.Name)17 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)16 JavacNode (lombok.javac.JavacNode)15 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)13 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)13 JCModifiers (com.sun.tools.javac.tree.JCTree.JCModifiers)10 JCClassDecl (com.sun.tools.javac.tree.JCTree.JCClassDecl)9 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)8 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)5 JCMethodInvocation (com.sun.tools.javac.tree.JCTree.JCMethodInvocation)5 JCPrimitiveTypeTree (com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree)5 ArrayList (java.util.ArrayList)5 JCArrayTypeTree (com.sun.tools.javac.tree.JCTree.JCArrayTypeTree)4 JCFieldAccess (com.sun.tools.javac.tree.JCTree.JCFieldAccess)4 Context (com.sun.tools.javac.util.Context)4 List (com.sun.tools.javac.util.List)4