/** * Copyright (C) 2005 - 2012 Eric Van Dewoestine * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.eclim.plugin.jdt.command.junit; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.eclim.Services; import org.eclim.annotation.Command; import org.eclim.command.CommandLine; import org.eclim.command.Options; import org.eclim.plugin.core.util.ProjectUtils; import org.eclim.plugin.core.util.TemplateUtils; import org.eclim.plugin.jdt.PluginResources; import org.eclim.plugin.jdt.command.impl.ImplCommand; import org.eclim.plugin.jdt.util.JavaUtils; import org.eclim.plugin.jdt.util.MethodUtils; import org.eclim.plugin.jdt.util.TypeInfo; import org.eclim.plugin.jdt.util.TypeUtils; import org.eclim.util.CollectionUtils; import org.eclim.util.file.Position; import org.eclipse.core.resources.IProject; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.formatter.CodeFormatter; /** * Command to handle creation of junit test stubs. * * @author Eric Van Dewoestine */ @Command( name = "java_junit_impl", options = "REQUIRED p project ARG," + "REQUIRED f file ARG," + "OPTIONAL o offset ARG," + "OPTIONAL e encoding ARG," + "OPTIONAL t type ARG," + "OPTIONAL b baseType ARG," + "OPTIONAL s superType ARG," + "OPTIONAL m methods ARG" ) public class JUnitImplCommand extends ImplCommand { private static final String JUNIT_TEMPLATE = "junit<version>_method.gst"; /** * {@inheritDoc} */ @Override protected TypeInfo[] getSuperTypes(CommandLine commandLine, IType type) throws Exception { ArrayList<TypeInfo> types = new ArrayList<TypeInfo>(); String baseType = commandLine.getValue(Options.BASETYPE_OPTION); if(baseType != null){ IType base = type.getJavaProject().findType(baseType); types.add(new TypeInfo(base, null, null)); TypeInfo[] baseTypes = super.getSuperTypes(commandLine, base); CollectionUtils.addAll(types, baseTypes); } TypeInfo[] testTypes = super.getSuperTypes(commandLine, type); for(int ii = 0; ii < testTypes.length; ii ++){ if(!types.contains(testTypes[ii])){ types.add(testTypes[ii]); } } return (TypeInfo[])types.toArray(new TypeInfo[types.size()]); } /** * {@inheritDoc} */ @Override protected boolean isValidMethod(IMethod method) throws Exception { String parent = ((IType)method.getParent()).getFullyQualifiedName(); if("java.lang.Object".equals(parent)){ return super.isValidMethod(method); } int flags = method.getFlags(); return (!Flags.isPrivate(flags) && !method.isConstructor() && !"junit.framework.Assert".equals(parent)); } /** * {@inheritDoc} */ @Override protected boolean isValidType(IType type) throws Exception { return true; } /** * {@inheritDoc} */ @Override protected IMethod getImplemented( IType type, Map<String, IMethod> baseMethods, TypeInfo superTypeInfo, IMethod method) throws Exception { IMethod base = baseMethods.get( MethodUtils.getMinimalMethodSignature(method, superTypeInfo)); if(base != null){ return base; } return baseMethods.get(getTestMethodSignature(type, method)); } /** * Gets a string representation of the test method equivalent of the supplied * method. * * @param type The type to be modified. * @param method The method. * @return The test method signature. */ protected String getTestMethodSignature(IType type, IMethod method) throws Exception { String version = ProjectUtils.getSetting( type.getJavaProject().getProject(), "org.eclim.java.junit.version"); String name = method.getElementName(); if (version.equals("3")){ name = "test" + StringUtils.capitalize(name); } StringBuffer buffer = new StringBuffer(); buffer.append(name).append("()"); return buffer.toString(); } /** * {@inheritDoc} */ @Override protected Position insertMethod( CommandLine commandLine, ICompilationUnit src, IType type, TypeInfo superTypeInfo, IMethod method, IJavaElement sibling) throws Exception { IType superType = superTypeInfo.getType(); String baseType = commandLine.getValue(Options.BASETYPE_OPTION); if(baseType != null){ IType base = type.getJavaProject().findType(baseType); if(base.equals(superType)){ return insertTestMethod(src, type, superTypeInfo, method, sibling); }else{ TypeInfo[] superTypesInfo = TypeUtils.getSuperTypes(base); for (TypeInfo info : superTypesInfo){ if(info.getType().equals(superType)){ return insertTestMethod(src, type, superTypeInfo, method, sibling); } } } } return super.insertMethod( commandLine, src, type, superTypeInfo, method, sibling); } /** * Inserts a test method stub for the supplied method. * * @param src The compilation unit. * @param type The type to insert the method into. * @param superTypeInfo The super type the method is defined in. * @param method The method to insert. * @param sibling The element to insert the new method before, or null to * append to the end. * @return The position the method was inserted at. */ protected Position insertTestMethod( ICompilationUnit src, IType type, TypeInfo superTypeInfo, IMethod method, IJavaElement sibling) throws Exception { IProject project = type.getJavaProject().getProject(); HashMap<String, Object> values = new HashMap<String, Object>(); JavaUtils.loadPreferencesForTemplate(project, getPreferences(), values); String version = ProjectUtils.getSetting(project, "org.eclim.java.junit.version"); String name = method.getElementName(); if (version.equals("3")){ name = "test" + StringUtils.capitalize(name); } values.put("name", name); values.put("methodName", method.getElementName()); values.put("superType", superTypeInfo.getType().getFullyQualifiedName()); values.put("methodSignatures", getMethodSignatures(superTypeInfo, method)); values.put("methodBody", null); PluginResources resources = (PluginResources) Services.getPluginResources(PluginResources.NAME); String template = JUNIT_TEMPLATE.replace("<version>", version); String result = TemplateUtils.evaluate(resources, template, values); Position position = TypeUtils.getPosition(type, type.createMethod(result, sibling, false, null)); JavaUtils.format( src, CodeFormatter.K_COMPILATION_UNIT, position.getOffset(), position.getLength()); return position; } /** * Constructs an array of method signatures. * * @param typeInfo The type to grab the methods from. * @param method The method or one of the overloaded methods to construct an * array from. * @return Array of method signatures. */ protected String[] getMethodSignatures(TypeInfo typeInfo, IMethod method) throws Exception { ArrayList<String> signatures = new ArrayList<String>(); IMethod[] methods = typeInfo.getType().getMethods(); for (int ii = 0; ii < methods.length; ii++){ if(methods[ii].getElementName().equals(method.getElementName())){ String sig = MethodUtils.getMinimalMethodSignature(methods[ii], typeInfo); signatures.add(sig); } } return (String[])signatures.toArray(new String[signatures.size()]); } }