Search in sources :

Example 21 with TypeDeclaration

use of org.eclipse.jdt.internal.compiler.ast.TypeDeclaration in project che by eclipse.

the class SourceTypeConverter method convert.

/*
	 * Convert a source element type into a parsed type declaration
	 */
private TypeDeclaration convert(SourceType typeHandle, CompilationResult compilationResult) throws JavaModelException {
    SourceTypeElementInfo typeInfo = (SourceTypeElementInfo) typeHandle.getElementInfo();
    if (typeInfo.isAnonymousMember())
        throw new AnonymousMemberFound();
    /* create type declaration - can be member type */
    TypeDeclaration type = new TypeDeclaration(compilationResult);
    if (typeInfo.getEnclosingType() == null) {
        if (typeHandle.isAnonymous()) {
            type.name = CharOperation.NO_CHAR;
            type.bits |= (ASTNode.IsAnonymousType | ASTNode.IsLocalType);
        } else {
            if (typeHandle.isLocal()) {
                type.bits |= ASTNode.IsLocalType;
            }
        }
    } else {
        type.bits |= ASTNode.IsMemberType;
    }
    if ((type.bits & ASTNode.IsAnonymousType) == 0) {
        type.name = typeInfo.getName();
    }
    type.name = typeInfo.getName();
    // only positions available
    int start, end;
    type.sourceStart = start = typeInfo.getNameSourceStart();
    type.sourceEnd = end = typeInfo.getNameSourceEnd();
    type.modifiers = typeInfo.getModifiers();
    type.declarationSourceStart = typeInfo.getDeclarationSourceStart();
    type.declarationSourceEnd = typeInfo.getDeclarationSourceEnd();
    type.bodyEnd = type.declarationSourceEnd;
    // convert 1.5 specific constructs only if compliance is 1.5 or above
    if (this.has1_5Compliance) {
        /* convert annotations */
        type.annotations = convertAnnotations(typeHandle);
    }
    /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, even in a 1.4 project, we
		   must internalize type variables and observe any parameterization of super class
		   and/or super interfaces in order to be able to detect overriding in the presence
		   of generics.
		 */
    char[][] typeParameterNames = typeInfo.getTypeParameterNames();
    if (typeParameterNames.length > 0) {
        int parameterCount = typeParameterNames.length;
        char[][][] typeParameterBounds = typeInfo.getTypeParameterBounds();
        type.typeParameters = new TypeParameter[parameterCount];
        for (int i = 0; i < parameterCount; i++) {
            type.typeParameters[i] = createTypeParameter(typeParameterNames[i], typeParameterBounds[i], start, end);
        }
    }
    /* set superclass and superinterfaces */
    if (typeInfo.getSuperclassName() != null) {
        type.superclass = createTypeReference(typeInfo.getSuperclassName(), start, end, true);
        type.superclass.bits |= ASTNode.IsSuperType;
    }
    char[][] interfaceNames = typeInfo.getInterfaceNames();
    int interfaceCount = interfaceNames == null ? 0 : interfaceNames.length;
    if (interfaceCount > 0) {
        type.superInterfaces = new TypeReference[interfaceCount];
        for (int i = 0; i < interfaceCount; i++) {
            type.superInterfaces[i] = createTypeReference(interfaceNames[i], start, end, true);
            type.superInterfaces[i].bits |= ASTNode.IsSuperType;
        }
    }
    /* convert member types */
    if ((this.flags & MEMBER_TYPE) != 0) {
        SourceType[] sourceMemberTypes = typeInfo.getMemberTypeHandles();
        int sourceMemberTypeCount = sourceMemberTypes.length;
        type.memberTypes = new TypeDeclaration[sourceMemberTypeCount];
        for (int i = 0; i < sourceMemberTypeCount; i++) {
            type.memberTypes[i] = convert(sourceMemberTypes[i], compilationResult);
            type.memberTypes[i].enclosingType = type;
        }
    }
    /* convert intializers and fields*/
    InitializerElementInfo[] initializers = null;
    int initializerCount = 0;
    if ((this.flags & LOCAL_TYPE) != 0) {
        initializers = typeInfo.getInitializers();
        initializerCount = initializers.length;
    }
    SourceField[] sourceFields = null;
    int sourceFieldCount = 0;
    if ((this.flags & FIELD) != 0) {
        sourceFields = typeInfo.getFieldHandles();
        sourceFieldCount = sourceFields.length;
    }
    int length = initializerCount + sourceFieldCount;
    if (length > 0) {
        type.fields = new FieldDeclaration[length];
        for (int i = 0; i < initializerCount; i++) {
            type.fields[i] = convert(initializers[i], compilationResult);
        }
        int index = 0;
        for (int i = initializerCount; i < length; i++) {
            type.fields[i] = convert(sourceFields[index++], type, compilationResult);
        }
    }
    /* convert methods - need to add default constructor if necessary */
    boolean needConstructor = (this.flags & CONSTRUCTOR) != 0;
    boolean needMethod = (this.flags & METHOD) != 0;
    if (needConstructor || needMethod) {
        SourceMethod[] sourceMethods = typeInfo.getMethodHandles();
        int sourceMethodCount = sourceMethods.length;
        /* source type has a constructor ?           */
        /* by default, we assume that one is needed. */
        int extraConstructor = 0;
        int methodCount = 0;
        int kind = TypeDeclaration.kind(type.modifiers);
        boolean isAbstract = kind == TypeDeclaration.INTERFACE_DECL || kind == TypeDeclaration.ANNOTATION_TYPE_DECL;
        if (!isAbstract) {
            extraConstructor = needConstructor ? 1 : 0;
            for (int i = 0; i < sourceMethodCount; i++) {
                if (sourceMethods[i].isConstructor()) {
                    if (needConstructor) {
                        // Does not need the extra constructor since one constructor already exists.
                        extraConstructor = 0;
                        methodCount++;
                    }
                } else if (needMethod) {
                    methodCount++;
                }
            }
        } else {
            methodCount = needMethod ? sourceMethodCount : 0;
        }
        type.methods = new AbstractMethodDeclaration[methodCount + extraConstructor];
        if (extraConstructor != 0) {
            // add default constructor in first position
            type.methods[0] = type.createDefaultConstructor(false, false);
        }
        int index = 0;
        boolean hasAbstractMethods = false;
        for (int i = 0; i < sourceMethodCount; i++) {
            SourceMethod sourceMethod = sourceMethods[i];
            SourceMethodElementInfo methodInfo = (SourceMethodElementInfo) sourceMethod.getElementInfo();
            boolean isConstructor = methodInfo.isConstructor();
            if ((methodInfo.getModifiers() & ClassFileConstants.AccAbstract) != 0) {
                hasAbstractMethods = true;
            }
            if ((isConstructor && needConstructor) || (!isConstructor && needMethod)) {
                AbstractMethodDeclaration method = convert(sourceMethod, methodInfo, compilationResult);
                if (isAbstract || method.isAbstract()) {
                    // fix-up flag
                    method.modifiers |= ExtraCompilerModifiers.AccSemicolonBody;
                }
                type.methods[extraConstructor + index++] = method;
            }
        }
        if (hasAbstractMethods)
            type.bits |= ASTNode.HasAbstractMethods;
    }
    return type;
}
Also used : SourceMethodElementInfo(org.eclipse.jdt.internal.core.SourceMethodElementInfo) ISourceType(org.eclipse.jdt.internal.compiler.env.ISourceType) SourceType(org.eclipse.jdt.internal.core.SourceType) SourceField(org.eclipse.jdt.internal.core.SourceField) InitializerElementInfo(org.eclipse.jdt.internal.core.InitializerElementInfo) SourceTypeElementInfo(org.eclipse.jdt.internal.core.SourceTypeElementInfo) SourceMethod(org.eclipse.jdt.internal.core.SourceMethod) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) AbstractMethodDeclaration(org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration)

Example 22 with TypeDeclaration

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

the class HandleConstructor method checkLegality.

static boolean checkLegality(EclipseNode typeNode, EclipseNode errorNode, String name) {
    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) {
        errorNode.addError(name + " is only supported on a class or an enum.");
        return false;
    }
    return true;
}
Also used : TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)

Example 23 with TypeDeclaration

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

the class HandleData method handle.

@Override
public void handle(AnnotationValues<Data> annotation, Annotation ast, EclipseNode annotationNode) {
    handleFlagUsage(annotationNode, ConfigurationKeys.DATA_FLAG_USAGE, "@Data");
    Data 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("@Data is only supported on a class.");
        return;
    }
    //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 @Data. 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 HandleSetter().generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
    new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
    new HandleToString().generateToStringForType(typeNode, annotationNode);
    new HandleConstructor().generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES, Collections.<Annotation>emptyList(), annotationNode);
}
Also used : EclipseNode(lombok.eclipse.EclipseNode) Data(lombok.Data) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)

Example 24 with TypeDeclaration

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

the class HandleEqualsAndHashCode method createTypeReference.

/**
	 * @param type Type to 'copy' into a typeref
	 * @param p position
	 * @param addWildcards If false, all generics are cut off. If true, replaces all genericparams with a ?.
	 * @return
	 */
public TypeReference createTypeReference(EclipseNode type, long p, ASTNode source, boolean addWildcards) {
    int pS = source.sourceStart;
    int pE = source.sourceEnd;
    List<String> list = new ArrayList<String>();
    list.add(type.getName());
    EclipseNode tNode = type.up();
    while (tNode != null && tNode.getKind() == Kind.TYPE) {
        list.add(tNode.getName());
        tNode = tNode.up();
    }
    Collections.reverse(list);
    TypeDeclaration typeDecl = (TypeDeclaration) type.get();
    int typeParamCount = typeDecl.typeParameters == null ? 0 : typeDecl.typeParameters.length;
    if (typeParamCount == 0)
        addWildcards = false;
    TypeReference[] typeArgs = null;
    if (addWildcards) {
        typeArgs = new TypeReference[typeParamCount];
        for (int i = 0; i < typeParamCount; i++) {
            typeArgs[i] = new Wildcard(Wildcard.UNBOUND);
            typeArgs[i].sourceStart = pS;
            typeArgs[i].sourceEnd = pE;
            setGeneratedBy(typeArgs[i], source);
        }
    }
    if (list.size() == 1) {
        if (addWildcards) {
            return new ParameterizedSingleTypeReference(list.get(0).toCharArray(), typeArgs, 0, p);
        } else {
            return new SingleTypeReference(list.get(0).toCharArray(), p);
        }
    }
    long[] ps = new long[list.size()];
    char[][] tokens = new char[list.size()][];
    for (int i = 0; i < list.size(); i++) {
        ps[i] = p;
        tokens[i] = list.get(i).toCharArray();
    }
    if (addWildcards) {
        TypeReference[][] typeArgs2 = new TypeReference[tokens.length][];
        typeArgs2[typeArgs2.length - 1] = typeArgs;
        return new ParameterizedQualifiedTypeReference(tokens, typeArgs2, 0, ps);
    } else {
        return new QualifiedTypeReference(tokens, ps);
    }
}
Also used : ParameterizedQualifiedTypeReference(org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference) ArrayList(java.util.ArrayList) Wildcard(org.eclipse.jdt.internal.compiler.ast.Wildcard) ParameterizedSingleTypeReference(org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference) SingleTypeReference(org.eclipse.jdt.internal.compiler.ast.SingleTypeReference) ParameterizedSingleTypeReference(org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference) QualifiedTypeReference(org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) ParameterizedQualifiedTypeReference(org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference) EclipseNode(lombok.eclipse.EclipseNode) TypeReference(org.eclipse.jdt.internal.compiler.ast.TypeReference) ParameterizedSingleTypeReference(org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference) QualifiedTypeReference(org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) ParameterizedQualifiedTypeReference(org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference) SingleTypeReference(org.eclipse.jdt.internal.compiler.ast.SingleTypeReference) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)

Example 25 with TypeDeclaration

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

the class HandleEqualsAndHashCode method generateMethods.

public void generateMethods(EclipseNode typeNode, EclipseNode errorNode, List<String> excludes, List<String> includes, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List<Annotation> onParam) {
    assert excludes == null || includes == null;
    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("@EqualsAndHashCode is only supported on a class.");
        return;
    }
    boolean implicitCallSuper = callSuper == null;
    if (callSuper == null) {
        try {
            callSuper = ((Boolean) EqualsAndHashCode.class.getMethod("callSuper").getDefaultValue()).booleanValue();
        } catch (Exception ignore) {
            throw new InternalError("Lombok bug - this cannot happen - can't find callSuper field in EqualsAndHashCode annotation.");
        }
    }
    boolean isDirectDescendantOfObject = true;
    if (typeDecl.superclass != null) {
        String p = typeDecl.superclass.toString();
        isDirectDescendantOfObject = p.equals("Object") || p.equals("java.lang.Object");
    }
    if (isDirectDescendantOfObject && callSuper) {
        errorNode.addError("Generating equals/hashCode with a supercall to java.lang.Object is pointless.");
        return;
    }
    if (implicitCallSuper && !isDirectDescendantOfObject) {
        CallSuperType cst = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_CALL_SUPER);
        if (cst == null)
            cst = CallSuperType.WARN;
        switch(cst) {
            default:
            case WARN:
                errorNode.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
                callSuper = false;
                break;
            case SKIP:
                callSuper = false;
                break;
            case CALL:
                callSuper = true;
                break;
        }
    }
    List<EclipseNode> nodesForEquality = new ArrayList<EclipseNode>();
    if (includes != null) {
        for (EclipseNode child : typeNode.down()) {
            if (child.getKind() != Kind.FIELD)
                continue;
            FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
            if (includes.contains(new String(fieldDecl.name)))
                nodesForEquality.add(child);
        }
    } else {
        for (EclipseNode child : typeNode.down()) {
            if (child.getKind() != Kind.FIELD)
                continue;
            FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
            if (!filterField(fieldDecl))
                continue;
            //Skip transient fields.
            if ((fieldDecl.modifiers & ClassFileConstants.AccTransient) != 0)
                continue;
            //Skip excluded fields.
            if (excludes != null && excludes.contains(new String(fieldDecl.name)))
                continue;
            nodesForEquality.add(child);
        }
    }
    boolean isFinal = (typeDecl.modifiers & ClassFileConstants.AccFinal) != 0;
    boolean needsCanEqual = !isFinal || !isDirectDescendantOfObject;
    MemberExistsResult equalsExists = methodExists("equals", typeNode, 1);
    MemberExistsResult hashCodeExists = methodExists("hashCode", typeNode, 0);
    MemberExistsResult canEqualExists = methodExists("canEqual", typeNode, 1);
    switch(Collections.max(Arrays.asList(equalsExists, hashCodeExists))) {
        case EXISTS_BY_LOMBOK:
            return;
        case EXISTS_BY_USER:
            if (whineIfExists) {
                String msg = "Not generating equals and hashCode: A method with one of those names already exists. (Either both or none of these methods will be generated).";
                errorNode.addWarning(msg);
            } else if (equalsExists == MemberExistsResult.NOT_EXISTS || hashCodeExists == MemberExistsResult.NOT_EXISTS) {
                // This means equals OR hashCode exists and not both.
                // Even though we should suppress the message about not generating these, this is such a weird and surprising situation we should ALWAYS generate a warning.
                // The user code couldn't possibly (barring really weird subclassing shenanigans) be in a shippable state anyway; the implementations of these 2 methods are
                // all inter-related and should be written by the same entity.
                String msg = String.format("Not generating %s: One of equals or hashCode exists. " + "You should either write both of these or none of these (in the latter case, lombok generates them).", equalsExists == MemberExistsResult.NOT_EXISTS ? "equals" : "hashCode");
                errorNode.addWarning(msg);
            }
            return;
        case NOT_EXISTS:
        default:
    }
    MethodDeclaration equalsMethod = createEquals(typeNode, nodesForEquality, callSuper, errorNode.get(), fieldAccess, needsCanEqual, onParam);
    equalsMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration) typeNode.get()).scope);
    injectMethod(typeNode, equalsMethod);
    if (needsCanEqual && canEqualExists == MemberExistsResult.NOT_EXISTS) {
        MethodDeclaration canEqualMethod = createCanEqual(typeNode, errorNode.get(), onParam);
        canEqualMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration) typeNode.get()).scope);
        injectMethod(typeNode, canEqualMethod);
    }
    MethodDeclaration hashCodeMethod = createHashCode(typeNode, nodesForEquality, callSuper, errorNode.get(), fieldAccess);
    hashCodeMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration) typeNode.get()).scope);
    injectMethod(typeNode, hashCodeMethod);
}
Also used : MemberExistsResult(lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult) MethodDeclaration(org.eclipse.jdt.internal.compiler.ast.MethodDeclaration) EqualsAndHashCode(lombok.EqualsAndHashCode) ArrayList(java.util.ArrayList) FieldDeclaration(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) EclipseNode(lombok.eclipse.EclipseNode) CallSuperType(lombok.core.configuration.CallSuperType) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)

Aggregations

TypeDeclaration (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)44 EclipseNode (lombok.eclipse.EclipseNode)25 FieldDeclaration (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration)16 ArrayList (java.util.ArrayList)14 MethodDeclaration (org.eclipse.jdt.internal.compiler.ast.MethodDeclaration)12 AbstractMethodDeclaration (org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration)11 TypeReference (org.eclipse.jdt.internal.compiler.ast.TypeReference)7 AllocationExpression (org.eclipse.jdt.internal.compiler.ast.AllocationExpression)6 Expression (org.eclipse.jdt.internal.compiler.ast.Expression)6 SingleNameReference (org.eclipse.jdt.internal.compiler.ast.SingleNameReference)6 Annotation (org.eclipse.jdt.internal.compiler.ast.Annotation)5 ClassLiteralAccess (org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess)5 ConstructorDeclaration (org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration)5 QualifiedTypeReference (org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference)5 SingleTypeReference (org.eclipse.jdt.internal.compiler.ast.SingleTypeReference)5 Statement (org.eclipse.jdt.internal.compiler.ast.Statement)5 ThisReference (org.eclipse.jdt.internal.compiler.ast.ThisReference)5 TypeParameter (org.eclipse.jdt.internal.compiler.ast.TypeParameter)5 Argument (org.eclipse.jdt.internal.compiler.ast.Argument)4 ISourceType (org.eclipse.jdt.internal.compiler.env.ISourceType)4