Search in sources :

Example 1 with Delegate

use of lombok.experimental.Delegate 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)

Aggregations

Type (com.sun.tools.javac.code.Type)1 ClassType (com.sun.tools.javac.code.Type.ClassType)1 JCTree (com.sun.tools.javac.tree.JCTree)1 JCFieldAccess (com.sun.tools.javac.tree.JCTree.JCFieldAccess)1 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)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 JavacResolution (lombok.javac.JavacResolution)1