/* * 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 org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.IMemberValuePairBinding; 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.MethodInvocation; import org.eclipse.jdt.core.dom.TypeDeclaration; public class MockUtil { public static final String MOCK = "mockit.Mock"; public static final String MOCKIT = "mockit.Mockit"; public static final String MOCK_UP = "mockit.MockUp"; public static final String MOCK_CLASS = "mockit.MockClass"; public static final String CLASSINIT = "$clinit"; public static final String CTOR = "$init"; public static final String GET_INST = "getMockInstance"; /** * Tests if the method is a mock-method for (static) class initializers. * @param meth The mock-method to test. * @return {@code true} if the method is a mock-method for (static) class initializers */ public static boolean isClassInitializerMock(final IMethodBinding meth) { return meth != null && meth.getName().equals(CLASSINIT); } public static boolean isMockMethod(final IMethodBinding meth) { return meth != null && ASTUtil.isAnnotationPresent(meth.getAnnotations(), MOCK); } public static boolean isReentrantMockMethod(final IMethodBinding meth) { IAnnotationBinding ann = ASTUtil.findAnnotation(meth.getAnnotations(), MOCK); if (ann != null) { for (IMemberValuePairBinding pair : ann.getDeclaredMemberValuePairs()) { if ("reentrant".equals(pair.getName())) { return Boolean.valueOf(pair.getValue().toString()); } } } return false; } public static boolean hasMockClass(final ITypeBinding type) { return ASTUtil.findAnnotation(type.getAnnotations(), MOCK_CLASS) != null; } public static boolean isMockUpType(final ITypeBinding declaringClass) { return declaringClass != null && declaringClass.getQualifiedName().startsWith(MOCK_UP); } public static ITypeBinding findMockedType(final MethodInvocation node) { MethodDeclaration surroundingMeth = ASTUtil.findAncestor(node, MethodDeclaration.class); if (surroundingMeth != null) { return findMockedType(surroundingMeth, surroundingMeth.resolveBinding()); } else { return null; } } public static ITypeBinding findMockedType(final MethodDeclaration node, final IMethodBinding meth) { ITypeBinding typePar = null; if (meth == null) { return null; } ITypeBinding declaringClass = meth.getDeclaringClass(); boolean isMockClass = hasMockClass(declaringClass); boolean isMockUpType = isMockUpType(declaringClass.getSuperclass()); if (isMockUpType) { typePar = ASTUtil.getFirstTypeParameter(node.getParent()); } else if (isMockClass) { typePar = MockUtil.findRealClassType(declaringClass); } return typePar; } public static IMethodBinding findRealMethodInType(ITypeBinding type, IMethodBinding meth, AST ast) { return findRealMethodInType(type, meth.getName(), meth.getParameterTypes(), ast); } public static IMethodBinding findRealMethodInType(final ITypeBinding type, final String mname, final ITypeBinding[] paramTypes, final AST ast) { String name = mname; if( MockUtil.CTOR.equals(name) ) name = type.getName(); IMethodBinding origMethod = ASTUtil.findMethodInType(type, name, paramTypes); if( origMethod == null && type.isInterface() && ast != null ) // interfaces can mock Object.class methods { ITypeBinding objType = ast.resolveWellKnownType(Object.class.getName()); origMethod = ASTUtil.findMethodInType(objType, name, paramTypes); } if (origMethod == null && type.getTypeArguments().length != 0) { // no method matches exactly, there could be type arguments (which we don't handle yet) origMethod = ASTUtil.findMethodInType(type, name, null); // match without params if (origMethod != null && origMethod.getParameterTypes().length != paramTypes.length) { origMethod = null; } } return origMethod; } public static ITypeBinding findRealClassType(final ITypeBinding mockClass) { IAnnotationBinding ann = ASTUtil.findAnnotation(mockClass.getAnnotations(), MOCK_CLASS); for (IMemberValuePairBinding pair : ann.getDeclaredMemberValuePairs()) { if ("realClass".equals(pair.getName())) { if (pair.getValue() instanceof ITypeBinding) { return (ITypeBinding) pair.getValue(); } } } return null; } public static ITypeBinding findMockedTypeFromNode(final ASTNode node) { ITypeBinding declaringType = null; if (node instanceof AnonymousClassDeclaration) { declaringType = ASTUtil.getFirstTypeParameter( (AnonymousClassDeclaration) node); } else if( node instanceof TypeDeclaration ) { TypeDeclaration typeDec = (TypeDeclaration) node; ITypeBinding curType = typeDec.resolveBinding(); if( hasMockClass(curType) ) { declaringType = findRealClassType(curType); } else if( isMockUpType(curType.getSuperclass()) ) { declaringType = ASTUtil.getFirstTypeParam(typeDec.getSuperclassType()); } } return declaringType; } public static ITypeBinding getMockType(final ASTNode node) { ITypeBinding mockType = null; if (node instanceof AnonymousClassDeclaration) { mockType = ((AnonymousClassDeclaration) node).resolveBinding(); } else if( node instanceof TypeDeclaration ) { mockType = ((TypeDeclaration) node).resolveBinding(); } return mockType; } }