Search in sources :

Example 41 with EclipseNode

use of lombok.eclipse.EclipseNode in project lombok by rzwitserloot.

the class HandleGetter method generateGetterForType.

public boolean generateGetterForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean checkForTypeLevelGetter) {
    if (checkForTypeLevelGetter) {
        if (hasAnnotation(Getter.class, typeNode)) {
            //The annotation will make it happen, so we can skip it.
            return true;
        }
    }
    TypeDeclaration typeDecl = null;
    if (typeNode.get() instanceof TypeDeclaration)
        typeDecl = (TypeDeclaration) typeNode.get();
    int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
    boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation)) != 0;
    if (typeDecl == null || notAClass) {
        pos.addError("@Getter is only supported on a class, an enum, or a field.");
        return false;
    }
    for (EclipseNode field : typeNode.down()) {
        if (fieldQualifiesForGetterGeneration(field))
            generateGetterForField(field, pos.get(), level, false);
    }
    return true;
}
Also used : EclipseNode(lombok.eclipse.EclipseNode) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)

Example 42 with EclipseNode

use of lombok.eclipse.EclipseNode in project lombok by rzwitserloot.

the class HandleHelper method handle.

@Override
public void handle(AnnotationValues<Helper> annotation, Annotation ast, EclipseNode annotationNode) {
    handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.HELPER_FLAG_USAGE, "@Helper");
    EclipseNode annotatedType = annotationNode.up();
    EclipseNode containingBlock = annotatedType == null ? null : annotatedType.directUp();
    Statement[] origStatements = getStatementsFromAstNode(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;
    }
    TypeDeclaration annotatedType_ = (TypeDeclaration) annotatedType.get();
    int indexOfType = -1;
    for (int i = 0; i < origStatements.length; i++) {
        if (origStatements[i] == annotatedType_) {
            indexOfType = i;
            break;
        }
    }
    final List<String> knownMethodNames = new ArrayList<String>();
    for (AbstractMethodDeclaration methodOfHelper : annotatedType_.methods) {
        if (!(methodOfHelper instanceof MethodDeclaration))
            continue;
        char[] name = methodOfHelper.selector;
        if (name != null && name.length > 0 && name[0] != '<')
            knownMethodNames.add(new String(name));
    }
    Collections.sort(knownMethodNames);
    final String[] knownMethodNames_ = knownMethodNames.toArray(new String[knownMethodNames.size()]);
    final char[] helperName = new char[annotatedType_.name.length + 1];
    final boolean[] helperUsed = new boolean[1];
    helperName[0] = '$';
    System.arraycopy(annotatedType_.name, 0, helperName, 1, helperName.length - 1);
    ASTVisitor visitor = new ASTVisitor() {

        @Override
        public boolean visit(MessageSend messageSend, BlockScope scope) {
            if (messageSend.receiver instanceof ThisReference) {
                if ((((ThisReference) messageSend.receiver).bits & ASTNode.IsImplicitThis) == 0)
                    return true;
            } else if (messageSend.receiver != null)
                return true;
            char[] name = messageSend.selector;
            if (name == null || name.length == 0 || name[0] == '<')
                return true;
            String n = new String(name);
            if (Arrays.binarySearch(knownMethodNames_, n) < 0)
                return true;
            messageSend.receiver = new SingleNameReference(helperName, messageSend.nameSourcePosition);
            helperUsed[0] = true;
            return true;
        }
    };
    for (int i = indexOfType + 1; i < origStatements.length; i++) {
        origStatements[i].traverse(visitor, null);
    }
    if (!helperUsed[0]) {
        annotationNode.addWarning("No methods of this helper class are ever used.");
        return;
    }
    Statement[] newStatements = new Statement[origStatements.length + 1];
    System.arraycopy(origStatements, 0, newStatements, 0, indexOfType + 1);
    System.arraycopy(origStatements, indexOfType + 1, newStatements, indexOfType + 2, origStatements.length - indexOfType - 1);
    LocalDeclaration decl = new LocalDeclaration(helperName, 0, 0);
    decl.modifiers |= ClassFileConstants.AccFinal;
    AllocationExpression alloc = new AllocationExpression();
    alloc.type = new SingleTypeReference(annotatedType_.name, 0L);
    decl.initialization = alloc;
    decl.type = new SingleTypeReference(annotatedType_.name, 0L);
    SetGeneratedByVisitor sgbvVisitor = new SetGeneratedByVisitor(annotationNode.get());
    decl.traverse(sgbvVisitor, null);
    newStatements[indexOfType + 1] = decl;
    setStatementsOfAstNode(containingBlock.get(), newStatements);
}
Also used : LocalDeclaration(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) Statement(org.eclipse.jdt.internal.compiler.ast.Statement) SwitchStatement(org.eclipse.jdt.internal.compiler.ast.SwitchStatement) MethodDeclaration(org.eclipse.jdt.internal.compiler.ast.MethodDeclaration) AbstractMethodDeclaration(org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration) ArrayList(java.util.ArrayList) ThisReference(org.eclipse.jdt.internal.compiler.ast.ThisReference) SingleNameReference(org.eclipse.jdt.internal.compiler.ast.SingleNameReference) ASTVisitor(org.eclipse.jdt.internal.compiler.ASTVisitor) MessageSend(org.eclipse.jdt.internal.compiler.ast.MessageSend) AllocationExpression(org.eclipse.jdt.internal.compiler.ast.AllocationExpression) SingleTypeReference(org.eclipse.jdt.internal.compiler.ast.SingleTypeReference) BlockScope(org.eclipse.jdt.internal.compiler.lookup.BlockScope) EclipseNode(lombok.eclipse.EclipseNode) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) AbstractMethodDeclaration(org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration)

Example 43 with EclipseNode

use of lombok.eclipse.EclipseNode in project lombok by rzwitserloot.

the class HandleUtilityClass method handle.

@Override
public void handle(AnnotationValues<UtilityClass> annotation, Annotation ast, EclipseNode annotationNode) {
    handleFlagUsage(annotationNode, ConfigurationKeys.UTILITY_CLASS_FLAG_USAGE, "@UtilityClass");
    EclipseNode typeNode = annotationNode.up();
    if (!checkLegality(typeNode, annotationNode))
        return;
    changeModifiersAndGenerateConstructor(annotationNode.up(), annotationNode);
}
Also used : EclipseNode(lombok.eclipse.EclipseNode)

Example 44 with EclipseNode

use of lombok.eclipse.EclipseNode in project lombok by rzwitserloot.

the class HandleUtilityClass method checkLegality.

private static boolean checkLegality(EclipseNode typeNode, EclipseNode errorNode) {
    TypeDeclaration typeDecl = null;
    if (typeNode.get() instanceof TypeDeclaration)
        typeDecl = (TypeDeclaration) typeNode.get();
    int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
    boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0;
    if (typeDecl == null || notAClass) {
        errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, or annotation).");
        return false;
    }
    // It might be an inner class. This is okay, but only if it is / can be a static inner class. Thus, all of its parents have to be static inner classes until the top-level.
    EclipseNode typeWalk = typeNode;
    while (true) {
        typeWalk = typeWalk.up();
        switch(typeWalk.getKind()) {
            case TYPE:
                if ((((TypeDeclaration) typeWalk.get()).modifiers & (ClassFileConstants.AccStatic | ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0)
                    continue;
                if (typeWalk.up().getKind() == Kind.COMPILATION_UNIT)
                    return true;
                errorNode.addError("@UtilityClass automatically makes the class static, however, this class cannot be made static.");
                return false;
            case COMPILATION_UNIT:
                return true;
            default:
                errorNode.addError("@UtilityClass cannot be placed on a method local or anonymous inner class, or any class nested in such a class.");
                return false;
        }
    }
}
Also used : EclipseNode(lombok.eclipse.EclipseNode) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)

Example 45 with EclipseNode

use of lombok.eclipse.EclipseNode in project lombok by rzwitserloot.

the class HandleValue method handle.

public void handle(AnnotationValues<Value> annotation, Annotation ast, EclipseNode annotationNode) {
    handleFlagUsage(annotationNode, ConfigurationKeys.VALUE_FLAG_USAGE, "@Value");
    Value ann = annotation.getInstance();
    EclipseNode typeNode = annotationNode.up();
    TypeDeclaration typeDecl = null;
    if (typeNode.get() instanceof TypeDeclaration)
        typeDecl = (TypeDeclaration) typeNode.get();
    int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
    boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0;
    if (typeDecl == null || notAClass) {
        annotationNode.addError("@Value is only supported on a class.");
        return;
    }
    // Make class final.
    if (!hasAnnotation(NonFinal.class, typeNode)) {
        if ((typeDecl.modifiers & ClassFileConstants.AccFinal) == 0) {
            typeDecl.modifiers |= ClassFileConstants.AccFinal;
            typeNode.rebuild();
        }
    }
    new HandleFieldDefaults().generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
    //Careful: Generate the public static constructor (if there is one) LAST, so that any attempt to
    //'find callers' on the annotation node will find callers of the constructor, which is by far the
    //most useful of the many methods built by @Value. This trick won't work for the non-static constructor,
    //for whatever reason, though you can find callers of that one by focusing on the class name itself
    //and hitting 'find callers'.
    new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
    new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
    new HandleToString().generateToStringForType(typeNode, annotationNode);
    new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES, Collections.<Annotation>emptyList(), annotationNode);
}
Also used : Value(lombok.Value) EclipseNode(lombok.eclipse.EclipseNode) NonFinal(lombok.experimental.NonFinal) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)

Aggregations

EclipseNode (lombok.eclipse.EclipseNode)55 TypeDeclaration (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)25 ArrayList (java.util.ArrayList)20 FieldDeclaration (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration)19 MethodDeclaration (org.eclipse.jdt.internal.compiler.ast.MethodDeclaration)16 Annotation (org.eclipse.jdt.internal.compiler.ast.Annotation)12 QualifiedTypeReference (org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference)11 TypeReference (org.eclipse.jdt.internal.compiler.ast.TypeReference)11 Expression (org.eclipse.jdt.internal.compiler.ast.Expression)10 SingleNameReference (org.eclipse.jdt.internal.compiler.ast.SingleNameReference)9 SingleTypeReference (org.eclipse.jdt.internal.compiler.ast.SingleTypeReference)9 AbstractMethodDeclaration (org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration)7 MessageSend (org.eclipse.jdt.internal.compiler.ast.MessageSend)7 ThisReference (org.eclipse.jdt.internal.compiler.ast.ThisReference)7 ParameterizedQualifiedTypeReference (org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference)6 ParameterizedSingleTypeReference (org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference)6 ReturnStatement (org.eclipse.jdt.internal.compiler.ast.ReturnStatement)6 Statement (org.eclipse.jdt.internal.compiler.ast.Statement)6 AllocationExpression (org.eclipse.jdt.internal.compiler.ast.AllocationExpression)5 Argument (org.eclipse.jdt.internal.compiler.ast.Argument)5