jmockit.assist.ASTUtil.java Source code

Java tutorial

Introduction

Here is the source code for jmockit.assist.ASTUtil.java

Source

/*
 * Copyright (c) 2012 Andrejs Jermakovics.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Andrejs Jermakovics - initial implementation
 */
package jmockit.assist;

import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.IAnnotationBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.ui.SharedASTProvider;

@SuppressWarnings("restriction")
public class ASTUtil {
    public static ITypeBinding getFirstTypeParameter(final ASTNode node) {
        ITypeBinding declaringType = null;

        if (node.getParent() instanceof ClassInstanceCreation) // for anonymous
        {
            ClassInstanceCreation creation = (ClassInstanceCreation) node.getParent();
            Type ctype = creation.getType();

            declaringType = getFirstTypeParam(ctype);
        } else if (node instanceof TypeDeclaration) {
            Type ctype = ((TypeDeclaration) node).getSuperclassType();
            declaringType = getFirstTypeParam(ctype);
        }

        return declaringType;
    }

    @SuppressWarnings("unchecked")
    public static ITypeBinding getFirstTypeParam(final Type ctype) {
        ITypeBinding declaringType = null;

        if (ctype instanceof ParameterizedType) {
            ParameterizedType paramType = (ParameterizedType) ctype;
            List<Type> typeArgs = paramType.typeArguments();

            if (!typeArgs.isEmpty()) {
                Type arg1 = typeArgs.get(0);
                declaringType = arg1.resolveBinding();
            }
        }
        return declaringType;
    }

    public static void addAnnotation(final String annotation, final IJavaProject project, final ASTRewrite rewrite,
            final MethodDeclaration decl, final IMethodBinding binding) {
        String version = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);

        if (!binding.getDeclaringClass().isInterface()
                || !JavaModelUtil.isVersionLessThan(version, JavaCore.VERSION_1_6)) {
            final Annotation marker = rewrite.getAST().newMarkerAnnotation();
            marker.setTypeName(rewrite.getAST().newSimpleName(annotation)); //$NON-NLS-1$
            rewrite.getListRewrite(decl, MethodDeclaration.MODIFIERS2_PROPERTY).insertFirst(marker, null);
        }
    }

    public static boolean isAnnotationPresent(final IAnnotationBinding[] annotations, final String annName) {
        return findAnnotation(annotations, annName) != null;
    }

    public static IAnnotationBinding findAnnotation(final IAnnotationBinding[] annotations, final String annName) {
        for (IAnnotationBinding ann : annotations) {
            if (annName.equals(ann.getAnnotationType().getQualifiedName())) {
                return ann;
            }
        }

        return null;
    }

    public static CompilationUnit getAstOrParse(final ITypeRoot iTypeRoot, final IProgressMonitor mon) {
        CompilationUnit cu = SharedASTProvider.getAST(iTypeRoot, SharedASTProvider.WAIT_NO, mon);

        if (cu == null && (mon == null || !mon.isCanceled())) {
            cu = parse(iTypeRoot, mon);
        }

        return cu;
    }

    public static CompilationUnit parse(final ITypeRoot unit, final IProgressMonitor mon) {
        ASTParser parser = ASTParser.newParser(AST.JLS3);
        parser.setKind(ASTParser.K_COMPILATION_UNIT);
        parser.setSource(unit);
        parser.setProject(unit.getJavaProject());
        parser.setResolveBindings(true);
        parser.setStatementsRecovery(true);
        return (CompilationUnit) parser.createAST(mon); // parse
    }

    @SuppressWarnings("unchecked")
    public static <T extends ASTNode> T findAncestor(final ASTNode node, final Class<T> clazz) {
        ASTNode parent = node.getParent();
        while (parent != null) {
            if (parent.getClass() == clazz) {
                break;
            }
            parent = parent.getParent();
        }
        return (T) parent;
    }

    public static IMethodBinding findMethodInType(final ITypeBinding type, final String name,
            final ITypeBinding[] paramTypes) {
        IMethodBinding origMethod;

        if (type.isInterface()) {
            origMethod = Bindings.findMethodInHierarchy(type, name, paramTypes);
        } else {
            origMethod = Bindings.findMethodInType(type, name, paramTypes);
        }

        return origMethod;
    }

    public static Set<String> getMethodSignatures(final ITypeBinding objType) throws JavaModelException {
        Set<String> methods = new TreeSet<String>();

        for (IMethodBinding m : objType.getDeclaredMethods()) {
            methods.add(getSig(m));
        }

        return methods;
    }

    public static String getSig(final IMethodBinding m) {
        String sig = m.getKey().split(";", 2)[1]; // remove declaring type
        return m.getName() + sig;
    }

    public static Collection<IMethodBinding> getAllMethods(final ITypeBinding paramType, final AST ast)
            throws JavaModelException {
        Set<IMethodBinding> methods = new TreeSet<IMethodBinding>(new Comparator<IMethodBinding>() {
            @Override
            public int compare(final IMethodBinding m1, final IMethodBinding m2) {
                return getSig(m1).compareTo(getSig(m2));
            }
        });

        methods.addAll(Arrays.asList(paramType.getDeclaredMethods()));

        if (paramType.isInterface()) {
            ITypeBinding[] superTypes = Bindings.getAllSuperTypes(paramType);

            for (ITypeBinding superType : superTypes) {
                methods.addAll(Arrays.asList(superType.getDeclaredMethods()));
            }

            ITypeBinding obj = ast.resolveWellKnownType(Object.class.getName());
            for (IMethodBinding m : obj.getDeclaredMethods()) {
                if (!m.isConstructor()) {
                    methods.add(m);
                }
            }
        }

        return methods;
    }
}