Search in sources :

Example 1 with Annotation

use of org.eclipse.jdt.internal.compiler.ast.Annotation in project lombok by rzwitserloot.

the class PatchDelegate method fillMethodBindingsForFields.

private static void fillMethodBindingsForFields(CompilationUnitDeclaration cud, ClassScope scope, List<BindingTuple> methodsToDelegate) {
    TypeDeclaration decl = scope.referenceContext;
    if (decl == null)
        return;
    if (decl.fields != null)
        for (FieldDeclaration field : decl.fields) {
            if (field.annotations == null)
                continue;
            for (Annotation ann : field.annotations) {
                if (!isDelegate(ann, decl))
                    continue;
                if (Annotation_applied.getAndSet(ann, true))
                    continue;
                if ((field.modifiers & ClassFileConstants.AccStatic) != 0) {
                    EclipseAST eclipseAst = TransformEclipseAST.getAST(cud, true);
                    eclipseAst.get(ann).addError(LEGALITY_OF_DELEGATE);
                    break;
                }
                List<ClassLiteralAccess> rawTypes = rawTypes(ann, "types");
                List<ClassLiteralAccess> excludedRawTypes = rawTypes(ann, "excludes");
                List<BindingTuple> methodsToExclude = new ArrayList<BindingTuple>();
                List<BindingTuple> methodsToDelegateForThisAnn = new ArrayList<BindingTuple>();
                try {
                    for (ClassLiteralAccess cla : excludedRawTypes) {
                        addAllMethodBindings(methodsToExclude, cla.type.resolveType(decl.initializerScope), new HashSet<String>(), field.name, ann);
                    }
                    Set<String> banList = new HashSet<String>();
                    for (BindingTuple excluded : methodsToExclude) banList.add(printSig(excluded.parameterized));
                    if (rawTypes.isEmpty()) {
                        addAllMethodBindings(methodsToDelegateForThisAnn, field.type.resolveType(decl.initializerScope), banList, field.name, ann);
                    } else {
                        for (ClassLiteralAccess cla : rawTypes) {
                            addAllMethodBindings(methodsToDelegateForThisAnn, cla.type.resolveType(decl.initializerScope), banList, field.name, ann);
                        }
                    }
                } catch (DelegateRecursion e) {
                    EclipseAST eclipseAst = TransformEclipseAST.getAST(cud, true);
                    eclipseAst.get(ann).addError(String.format(RECURSION_NOT_ALLOWED, new String(e.member), new String(e.type)));
                    break;
                }
                // Not doing this right now because of problems - see commented-out-method for info.
                // removeExistingMethods(methodsToDelegate, decl, scope);
                String dupe = containsDuplicates(methodsToDelegateForThisAnn);
                if (dupe != null) {
                    EclipseAST eclipseAst = TransformEclipseAST.getAST(cud, true);
                    eclipseAst.get(ann).addError("The method '" + dupe + "' is being delegated by more than one specified type.");
                } else {
                    methodsToDelegate.addAll(methodsToDelegateForThisAnn);
                }
            }
        }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) EclipseAST(lombok.eclipse.EclipseAST) TransformEclipseAST(lombok.eclipse.TransformEclipseAST) FieldDeclaration(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) Annotation(org.eclipse.jdt.internal.compiler.ast.Annotation) List(java.util.List) ArrayList(java.util.ArrayList) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) ClassLiteralAccess(org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess) HashSet(java.util.HashSet)

Example 2 with Annotation

use of org.eclipse.jdt.internal.compiler.ast.Annotation in project lombok by rzwitserloot.

the class PatchExtensionMethod method resolveType.

public static TypeBinding resolveType(TypeBinding resolvedType, MessageSend methodCall, BlockScope scope) {
    List<Extension> extensions = new ArrayList<Extension>();
    TypeDeclaration decl = scope.classScope().referenceContext;
    EclipseNode owningType = null;
    for (EclipseNode typeNode = getTypeNode(decl); typeNode != null; typeNode = upToType(typeNode)) {
        Annotation ann = getAnnotation(ExtensionMethod.class, typeNode);
        if (ann != null) {
            extensions.addAll(0, getApplicableExtensionMethods(typeNode, ann, methodCall.receiver.resolvedType));
            if (owningType == null)
                owningType = typeNode;
        }
    }
    boolean skip = false;
    if (methodCall.receiver instanceof ThisReference && (((ThisReference) methodCall.receiver).bits & ASTNode.IsImplicitThis) != 0)
        skip = true;
    if (methodCall.receiver instanceof SuperReference)
        skip = true;
    if (methodCall.receiver instanceof NameReference) {
        Binding binding = ((NameReference) methodCall.receiver).binding;
        if (binding instanceof TypeBinding)
            skip = true;
    }
    if (!skip)
        for (Extension extension : extensions) {
            if (!extension.suppressBaseMethods && !(methodCall.binding instanceof ProblemMethodBinding))
                continue;
            for (MethodBinding extensionMethod : extension.extensionMethods) {
                if (!Arrays.equals(methodCall.selector, extensionMethod.selector))
                    continue;
                MessageSend_postponedErrors.clear(methodCall);
                if (methodCall.receiver instanceof ThisReference) {
                    methodCall.receiver.bits &= ~ASTNode.IsImplicitThis;
                }
                List<Expression> arguments = new ArrayList<Expression>();
                arguments.add(methodCall.receiver);
                if (methodCall.arguments != null)
                    arguments.addAll(Arrays.asList(methodCall.arguments));
                List<TypeBinding> argumentTypes = new ArrayList<TypeBinding>();
                for (Expression argument : arguments) {
                    if (argument.resolvedType != null)
                        argumentTypes.add(argument.resolvedType);
                // TODO: Instead of just skipping nulls entirely, there is probably a 'unresolved type' placeholder. THAT is what we ought to be adding here!
                }
                Expression[] originalArgs = methodCall.arguments;
                methodCall.arguments = arguments.toArray(new Expression[0]);
                MethodBinding fixedBinding = scope.getMethod(extensionMethod.declaringClass, methodCall.selector, argumentTypes.toArray(new TypeBinding[0]), methodCall);
                if (fixedBinding instanceof ProblemMethodBinding) {
                    methodCall.arguments = originalArgs;
                    if (fixedBinding.declaringClass != null) {
                        PostponedInvalidMethodError.invoke(scope.problemReporter(), methodCall, fixedBinding, scope);
                    }
                } else {
                    for (int i = 0, iend = arguments.size(); i < iend; i++) {
                        Expression arg = arguments.get(i);
                        if (fixedBinding.parameters[i].isArrayType() != arg.resolvedType.isArrayType())
                            break;
                        if (arg instanceof MessageSend) {
                            ((MessageSend) arg).valueCast = arg.resolvedType;
                        }
                        if (!fixedBinding.parameters[i].isBaseType() && arg.resolvedType.isBaseType()) {
                            int id = arg.resolvedType.id;
                            // magic see TypeIds
                            arg.implicitConversion = TypeIds.BOXING | (id + (id << 4));
                        } else if (fixedBinding.parameters[i].isBaseType() && !arg.resolvedType.isBaseType()) {
                            int id = fixedBinding.parameters[i].id;
                            // magic see TypeIds
                            arg.implicitConversion = TypeIds.UNBOXING | (id + (id << 4));
                        }
                    }
                    methodCall.receiver = createNameRef(extensionMethod.declaringClass, methodCall);
                    methodCall.actualReceiverType = extensionMethod.declaringClass;
                    methodCall.binding = fixedBinding;
                    methodCall.resolvedType = methodCall.binding.returnType;
                }
                return methodCall.resolvedType;
            }
        }
    PostponedError error = MessageSend_postponedErrors.get(methodCall);
    if (error != null)
        error.fire();
    MessageSend_postponedErrors.clear(methodCall);
    return resolvedType;
}
Also used : Binding(org.eclipse.jdt.internal.compiler.lookup.Binding) TypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding) ProblemMethodBinding(org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding) MethodBinding(org.eclipse.jdt.internal.compiler.lookup.MethodBinding) ReferenceBinding(org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding) QualifiedNameReference(org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference) NameReference(org.eclipse.jdt.internal.compiler.ast.NameReference) SingleNameReference(org.eclipse.jdt.internal.compiler.ast.SingleNameReference) ProblemMethodBinding(org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding) TypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding) ArrayList(java.util.ArrayList) ThisReference(org.eclipse.jdt.internal.compiler.ast.ThisReference) EclipseHandlerUtil.createAnnotation(lombok.eclipse.handlers.EclipseHandlerUtil.createAnnotation) Annotation(org.eclipse.jdt.internal.compiler.ast.Annotation) SuperReference(org.eclipse.jdt.internal.compiler.ast.SuperReference) MessageSend(org.eclipse.jdt.internal.compiler.ast.MessageSend) Expression(org.eclipse.jdt.internal.compiler.ast.Expression) EclipseNode(lombok.eclipse.EclipseNode) ProblemMethodBinding(org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding) MethodBinding(org.eclipse.jdt.internal.compiler.lookup.MethodBinding) ArrayList(java.util.ArrayList) List(java.util.List) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)

Example 3 with Annotation

use of org.eclipse.jdt.internal.compiler.ast.Annotation in project lombok by rzwitserloot.

the class PatchExtensionMethodCompletionProposal method getExtensionMethods.

private static List<Extension> getExtensionMethods(CompletionProposalCollector completionProposalCollector) {
    List<Extension> extensions = new ArrayList<Extension>();
    ClassScope classScope = getClassScope(completionProposalCollector);
    if (classScope != null) {
        TypeDeclaration decl = classScope.referenceContext;
        TypeBinding firstParameterType = getFirstParameterType(decl, completionProposalCollector);
        for (EclipseNode typeNode = getTypeNode(decl); typeNode != null; typeNode = upToType(typeNode)) {
            Annotation ann = getAnnotation(ExtensionMethod.class, typeNode);
            extensions.addAll(0, getApplicableExtensionMethods(typeNode, ann, firstParameterType));
        }
    }
    return extensions;
}
Also used : Extension(lombok.eclipse.agent.PatchExtensionMethod.Extension) TypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding) ArrayList(java.util.ArrayList) EclipseNode(lombok.eclipse.EclipseNode) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) Annotation(org.eclipse.jdt.internal.compiler.ast.Annotation) ClassScope(org.eclipse.jdt.internal.compiler.lookup.ClassScope)

Example 4 with Annotation

use of org.eclipse.jdt.internal.compiler.ast.Annotation in project lombok by rzwitserloot.

the class PatchValEclipse method addFinalAndValAnnotationToModifierList.

public static void addFinalAndValAnnotationToModifierList(Object converter, List<IExtendedModifier> modifiers, AST ast, LocalDeclaration in) {
    // First check that 'in' has the final flag on, and a @val / @lombok.val annotation.
    if ((in.modifiers & ClassFileConstants.AccFinal) == 0)
        return;
    if (in.annotations == null)
        return;
    boolean found = false;
    Annotation valAnnotation = null;
    for (Annotation ann : in.annotations) {
        if (couldBeVal(ann.type)) {
            found = true;
            valAnnotation = ann;
            break;
        }
    }
    if (!found)
        return;
    // This is null only if the project is 1.4 or less. Lombok doesn't work in that.
    if (modifiers == null)
        return;
    boolean finalIsPresent = false;
    boolean valIsPresent = false;
    for (Object present : modifiers) {
        if (present instanceof Modifier) {
            ModifierKeyword keyword = ((Modifier) present).getKeyword();
            if (keyword == null)
                continue;
            if (keyword.toFlagValue() == Modifier.FINAL)
                finalIsPresent = true;
        }
        if (present instanceof org.eclipse.jdt.core.dom.Annotation) {
            Name typeName = ((org.eclipse.jdt.core.dom.Annotation) present).getTypeName();
            if (typeName != null) {
                String fullyQualifiedName = typeName.getFullyQualifiedName();
                if ("val".equals(fullyQualifiedName) || "lombok.val".equals(fullyQualifiedName)) {
                    valIsPresent = true;
                }
            }
        }
    }
    if (!finalIsPresent) {
        modifiers.add(createModifier(ast, ModifierKeyword.FINAL_KEYWORD, valAnnotation.sourceStart, valAnnotation.sourceEnd));
    }
    if (!valIsPresent) {
        MarkerAnnotation newAnnotation = createValAnnotation(ast, valAnnotation, valAnnotation.sourceStart, valAnnotation.sourceEnd);
        try {
            Reflection.astConverterRecordNodes.invoke(converter, newAnnotation, valAnnotation);
            Reflection.astConverterRecordNodes.invoke(converter, newAnnotation.getTypeName(), valAnnotation.type);
        } catch (IllegalAccessException e) {
            throw Lombok.sneakyThrow(e);
        } catch (InvocationTargetException e) {
            throw Lombok.sneakyThrow(e.getCause());
        }
        modifiers.add(newAnnotation);
    }
}
Also used : MarkerAnnotation(org.eclipse.jdt.core.dom.MarkerAnnotation) ModifierKeyword(org.eclipse.jdt.core.dom.Modifier.ModifierKeyword) IExtendedModifier(org.eclipse.jdt.core.dom.IExtendedModifier) Modifier(org.eclipse.jdt.core.dom.Modifier) MarkerAnnotation(org.eclipse.jdt.core.dom.MarkerAnnotation) Annotation(org.eclipse.jdt.internal.compiler.ast.Annotation) InvocationTargetException(java.lang.reflect.InvocationTargetException) SimpleName(org.eclipse.jdt.core.dom.SimpleName) Name(org.eclipse.jdt.core.dom.Name) QualifiedName(org.eclipse.jdt.core.dom.QualifiedName)

Example 5 with Annotation

use of org.eclipse.jdt.internal.compiler.ast.Annotation in project lombok by rzwitserloot.

the class HandleSetter method handle.

public void handle(AnnotationValues<Setter> annotation, Annotation ast, EclipseNode annotationNode) {
    handleFlagUsage(annotationNode, ConfigurationKeys.SETTER_FLAG_USAGE, "@Setter");
    EclipseNode node = annotationNode.up();
    AccessLevel level = annotation.getInstance().value();
    if (level == AccessLevel.NONE || node == null)
        return;
    List<Annotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod", annotationNode);
    List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam", annotationNode);
    switch(node.getKind()) {
        case FIELD:
            createSetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, true, onMethod, onParam);
            break;
        case TYPE:
            if (!onMethod.isEmpty()) {
                annotationNode.addError("'onMethod' is not supported for @Setter on a type.");
            }
            if (!onParam.isEmpty()) {
                annotationNode.addError("'onParam' is not supported for @Setter on a type.");
            }
            generateSetterForType(node, annotationNode, level, false);
            break;
    }
}
Also used : EclipseNode(lombok.eclipse.EclipseNode) AccessLevel(lombok.AccessLevel) Annotation(org.eclipse.jdt.internal.compiler.ast.Annotation)

Aggregations

Annotation (org.eclipse.jdt.internal.compiler.ast.Annotation)24 EclipseNode (lombok.eclipse.EclipseNode)12 ArrayList (java.util.ArrayList)11 Expression (org.eclipse.jdt.internal.compiler.ast.Expression)8 FieldDeclaration (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration)6 SingleMemberAnnotation (org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation)6 AllocationExpression (org.eclipse.jdt.internal.compiler.ast.AllocationExpression)5 QualifiedTypeReference (org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference)5 TypeDeclaration (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)5 List (java.util.List)4 AccessLevel (lombok.AccessLevel)4 MarkerAnnotation (org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation)4 MemberValuePair (org.eclipse.jdt.internal.compiler.ast.MemberValuePair)4 MethodDeclaration (org.eclipse.jdt.internal.compiler.ast.MethodDeclaration)4 NormalAnnotation (org.eclipse.jdt.internal.compiler.ast.NormalAnnotation)4 ReturnStatement (org.eclipse.jdt.internal.compiler.ast.ReturnStatement)4 Statement (org.eclipse.jdt.internal.compiler.ast.Statement)4 ASTNode (org.eclipse.jdt.internal.compiler.ast.ASTNode)3 Argument (org.eclipse.jdt.internal.compiler.ast.Argument)3 CastExpression (org.eclipse.jdt.internal.compiler.ast.CastExpression)3