Search in sources :

Example 1 with JavacResolution

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

the class HandleDelegate method handle.

@Override
public void handle(AnnotationValues<Delegate> annotation, JCAnnotation ast, JavacNode annotationNode) {
    handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.DELEGATE_FLAG_USAGE, "@Delegate");
    @SuppressWarnings("deprecation") Class<? extends Annotation> oldDelegate = lombok.Delegate.class;
    deleteAnnotationIfNeccessary(annotationNode, Delegate.class, oldDelegate);
    Type delegateType;
    Name delegateName = annotationNode.toName(annotationNode.up().getName());
    DelegateReceiver delegateReceiver;
    JavacResolution reso = new JavacResolution(annotationNode.getContext());
    JCTree member = annotationNode.up().get();
    if (annotationNode.up().getKind() == Kind.FIELD) {
        if ((((JCVariableDecl) member).mods.flags & Flags.STATIC) != 0) {
            annotationNode.addError(LEGALITY_OF_DELEGATE);
            return;
        }
        delegateReceiver = DelegateReceiver.FIELD;
        delegateType = member.type;
        if (delegateType == null)
            reso.resolveClassMember(annotationNode.up());
        delegateType = member.type;
    } else if (annotationNode.up().getKind() == Kind.METHOD) {
        if (!(member instanceof JCMethodDecl)) {
            annotationNode.addError(LEGALITY_OF_DELEGATE);
            return;
        }
        JCMethodDecl methodDecl = (JCMethodDecl) member;
        if (!methodDecl.params.isEmpty() || (methodDecl.mods.flags & Flags.STATIC) != 0) {
            annotationNode.addError(LEGALITY_OF_DELEGATE);
            return;
        }
        delegateReceiver = DelegateReceiver.METHOD;
        delegateType = methodDecl.restype.type;
        if (delegateType == null)
            reso.resolveClassMember(annotationNode.up());
        delegateType = methodDecl.restype.type;
    } else {
        // As the annotation is legal on fields and methods only, javac itself will take care of printing an error message for this.
        return;
    }
    List<Object> delegateTypes = annotation.getActualExpressions("types");
    List<Object> excludeTypes = annotation.getActualExpressions("excludes");
    List<Type> toDelegate = new ArrayList<Type>();
    List<Type> toExclude = new ArrayList<Type>();
    if (delegateTypes.isEmpty()) {
        if (delegateType != null)
            toDelegate.add(delegateType);
    } else {
        for (Object dt : delegateTypes) {
            if (dt instanceof JCFieldAccess && ((JCFieldAccess) dt).name.toString().equals("class")) {
                Type type = ((JCFieldAccess) dt).selected.type;
                if (type == null)
                    reso.resolveClassMember(annotationNode);
                type = ((JCFieldAccess) dt).selected.type;
                if (type != null)
                    toDelegate.add(type);
            }
        }
    }
    for (Object et : excludeTypes) {
        if (et instanceof JCFieldAccess && ((JCFieldAccess) et).name.toString().equals("class")) {
            Type type = ((JCFieldAccess) et).selected.type;
            if (type == null)
                reso.resolveClassMember(annotationNode);
            type = ((JCFieldAccess) et).selected.type;
            if (type != null)
                toExclude.add(type);
        }
    }
    List<MethodSig> signaturesToDelegate = new ArrayList<MethodSig>();
    List<MethodSig> signaturesToExclude = new ArrayList<MethodSig>();
    Set<String> banList = new HashSet<String>();
    banList.addAll(METHODS_IN_OBJECT);
    try {
        for (Type t : toExclude) {
            if (t instanceof ClassType) {
                ClassType ct = (ClassType) t;
                addMethodBindings(signaturesToExclude, ct, annotationNode.getTypesUtil(), banList);
            } else {
                annotationNode.addError("@Delegate can only use concrete class types, not wildcards, arrays, type variables, or primitives.");
                return;
            }
        }
        for (MethodSig sig : signaturesToExclude) {
            banList.add(printSig(sig.type, sig.name, annotationNode.getTypesUtil()));
        }
        for (Type t : toDelegate) {
            if (t instanceof ClassType) {
                ClassType ct = (ClassType) t;
                addMethodBindings(signaturesToDelegate, ct, annotationNode.getTypesUtil(), banList);
            } else {
                annotationNode.addError("@Delegate can only use concrete class types, not wildcards, arrays, type variables, or primitives.");
                return;
            }
        }
        for (MethodSig sig : signaturesToDelegate) generateAndAdd(sig, annotationNode, delegateName, delegateReceiver);
    } catch (DelegateRecursion e) {
        annotationNode.addError(String.format(RECURSION_NOT_ALLOWED, e.member, e.type));
    }
}
Also used : JavacResolution(lombok.javac.JavacResolution) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) ArrayList(java.util.ArrayList) JCTree(com.sun.tools.javac.tree.JCTree) ClassType(com.sun.tools.javac.code.Type.ClassType) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Name(com.sun.tools.javac.util.Name) ClassType(com.sun.tools.javac.code.Type.ClassType) Type(com.sun.tools.javac.code.Type) ExecutableType(javax.lang.model.type.ExecutableType) Delegate(lombok.experimental.Delegate) HashSet(java.util.HashSet)

Example 2 with JavacResolution

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

the class HandleVal method visitLocal.

@Override
public void visitLocal(JavacNode localNode, JCVariableDecl local) {
    JCTree typeTree = local.vartype;
    if (typeTree == null)
        return;
    String typeTreeToString = typeTree.toString();
    if (!(eq(typeTreeToString, "val") || eq(typeTreeToString, "var")))
        return;
    boolean isVal = typeMatches(val.class, localNode, typeTree);
    boolean isVar = typeMatches(var.class, localNode, typeTree);
    if (!(isVal || isVar))
        return;
    if (isVal)
        handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val");
    if (isVar)
        handleFlagUsage(localNode, ConfigurationKeys.VAR_FLAG_USAGE, "var");
    JCTree parentRaw = localNode.directUp().get();
    if (isVal && parentRaw instanceof JCForLoop) {
        localNode.addError("'val' is not allowed in old-style for loops");
        return;
    }
    JCExpression rhsOfEnhancedForLoop = null;
    if (local.init == null) {
        if (parentRaw instanceof JCEnhancedForLoop) {
            JCEnhancedForLoop efl = (JCEnhancedForLoop) parentRaw;
            if (efl.var == local)
                rhsOfEnhancedForLoop = efl.expr;
        }
    }
    final String annotation = typeTreeToString;
    if (rhsOfEnhancedForLoop == null && local.init == null) {
        localNode.addError("'" + annotation + "' on a local variable requires an initializer expression");
        return;
    }
    if (local.init instanceof JCNewArray && ((JCNewArray) local.init).elemtype == null) {
        localNode.addError("'" + annotation + "' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })");
        return;
    }
    if (localNode.shouldDeleteLombokAnnotations()) {
        JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, val.class.getName());
        JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, var.class.getName());
    }
    if (isVal)
        local.mods.flags |= Flags.FINAL;
    if (!localNode.shouldDeleteLombokAnnotations()) {
        JCAnnotation valAnnotation = recursiveSetGeneratedBy(localNode.getTreeMaker().Annotation(local.vartype, List.<JCExpression>nil()), typeTree, localNode.getContext());
        local.mods.annotations = local.mods.annotations == null ? List.of(valAnnotation) : local.mods.annotations.append(valAnnotation);
    }
    if (JavacResolution.platformHasTargetTyping()) {
        local.vartype = localNode.getAst().getTreeMaker().Ident(localNode.getAst().toName("___Lombok_VAL_Attrib__"));
    } else {
        local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
    }
    Type type;
    try {
        if (rhsOfEnhancedForLoop == null) {
            if (local.init.type == null) {
                if (isVar && local.init instanceof JCLiteral && ((JCLiteral) local.init).value == null) {
                    localNode.addError("variable initializer is 'null'");
                }
                JavacResolution resolver = new JavacResolution(localNode.getContext());
                try {
                    type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type;
                } catch (RuntimeException e) {
                    System.err.println("Exception while resolving: " + localNode);
                    throw e;
                }
            } else {
                type = local.init.type;
                if (type.isErroneous()) {
                    try {
                        JavacResolution resolver = new JavacResolution(localNode.getContext());
                        local.type = Symtab.instance(localNode.getContext()).unknownType;
                        type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type;
                    } catch (RuntimeException e) {
                        System.err.println("Exception while resolving: " + localNode);
                        throw e;
                    }
                }
            }
        } else {
            if (rhsOfEnhancedForLoop.type == null) {
                JavacResolution resolver = new JavacResolution(localNode.getContext());
                type = ((JCExpression) resolver.resolveMethodMember(localNode.directUp()).get(rhsOfEnhancedForLoop)).type;
            } else {
                type = rhsOfEnhancedForLoop.type;
            }
        }
        try {
            JCExpression replacement;
            if (rhsOfEnhancedForLoop != null) {
                Type componentType = JavacResolution.ifTypeIsIterableToComponent(type, localNode.getAst());
                if (componentType == null)
                    replacement = JavacResolution.createJavaLangObject(localNode.getAst());
                else
                    replacement = JavacResolution.typeToJCTree(componentType, localNode.getAst(), false);
            } else {
                replacement = JavacResolution.typeToJCTree(type, localNode.getAst(), false);
            }
            if (replacement != null) {
                local.vartype = replacement;
            } else {
                local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
            }
            localNode.getAst().setChanged();
        } catch (JavacResolution.TypeNotConvertibleException e) {
            localNode.addError("Cannot use '" + annotation + "' here because initializer expression does not have a representable type: " + e.getMessage());
            local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
        }
    } catch (RuntimeException e) {
        local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
        throw e;
    } finally {
        recursiveSetGeneratedBy(local.vartype, typeTree, localNode.getContext());
    }
}
Also used : lombok.val(lombok.val) JavacResolution(lombok.javac.JavacResolution) lombok.experimental.var(lombok.experimental.var) JCTree(com.sun.tools.javac.tree.JCTree) JCForLoop(com.sun.tools.javac.tree.JCTree.JCForLoop) Type(com.sun.tools.javac.code.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCEnhancedForLoop(com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop) JCLiteral(com.sun.tools.javac.tree.JCTree.JCLiteral) JCNewArray(com.sun.tools.javac.tree.JCTree.JCNewArray) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation)

Aggregations

Type (com.sun.tools.javac.code.Type)2 JCTree (com.sun.tools.javac.tree.JCTree)2 JavacResolution (lombok.javac.JavacResolution)2 ClassType (com.sun.tools.javac.code.Type.ClassType)1 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)1 JCEnhancedForLoop (com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop)1 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)1 JCFieldAccess (com.sun.tools.javac.tree.JCTree.JCFieldAccess)1 JCForLoop (com.sun.tools.javac.tree.JCTree.JCForLoop)1 JCLiteral (com.sun.tools.javac.tree.JCTree.JCLiteral)1 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)1 JCNewArray (com.sun.tools.javac.tree.JCTree.JCNewArray)1 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)1 Name (com.sun.tools.javac.util.Name)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 ExecutableType (javax.lang.model.type.ExecutableType)1 Delegate (lombok.experimental.Delegate)1 lombok.experimental.var (lombok.experimental.var)1 lombok.val (lombok.val)1