blob: 20832c21306231d6342411debe5d810b011d2402 [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2004, 2009 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute and Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
*
* 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
* $Id: RefactoringUtil.java 23473 2010-02-05 19:46:08Z stephan $
*
* Please visit http://www.objectteams.org for updates and contact.
*
* Contributors:
* Fraunhofer FIRST - Initial API and implementation
* Technical University Berlin - Initial API and implementation
* Johannes Gebauer - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otdt.internal.refactoring.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
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.AbstractMethodMappingDeclaration;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.CallinMappingDeclaration;
import org.eclipse.jdt.core.dom.CalloutMappingDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodMappingElement;
import org.eclipse.jdt.core.dom.MethodSpec;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.RoleTypeDeclaration;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.corext.Corext;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.internal.corext.refactoring.Checks;
import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2;
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
import org.eclipse.jdt.internal.corext.util.JdtFlags;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
import org.eclipse.objectteams.otdt.core.IMethodMapping;
import org.eclipse.objectteams.otdt.core.IOTType;
import org.eclipse.objectteams.otdt.core.IRoleType;
import org.eclipse.objectteams.otdt.core.OTModelManager;
import org.eclipse.objectteams.otdt.core.TypeHelper;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.core.search.OTSearchEngine;
import org.eclipse.objectteams.otdt.core.search.OTSearchRequestor;
import org.eclipse.objectteams.otdt.internal.core.InheritedMethodsRequestor;
import org.eclipse.objectteams.otdt.internal.core.OTTypeHierarchy;
import org.eclipse.objectteams.otdt.internal.core.OTTypeHierarchyTraverser;
import org.eclipse.objectteams.otdt.internal.refactoring.OTRefactoringPlugin;
import org.eclipse.objectteams.otdt.internal.refactoring.corext.OTRefactoringCoreMessages;
import org.eclipse.objectteams.otdt.internal.refactoring.corext.base.OTRefactoringStatusCodes;
/**
* This utility class is a part of the OT/J refactoring adaptation. It contains
* some OT refactoring related helper methods.
*
* @author brcan
*/
@SuppressWarnings("restriction")
public class RefactoringUtil implements ITeamConstants {
/**
* Checks whether the top-level type of the given compilation unit is a
* regular class or a team class.
*
* @param compUnit
* the given compilation unit
* @param str
* the string describing the error
* @return the refactoring status
* @throws JavaModelException
*/
public static RefactoringStatus checkOOClass(ICompilationUnit compUnit, String str) throws JavaModelException {
RefactoringStatus status = new RefactoringStatus();
IType type = robustFindPrimaryType(compUnit);
if (Flags.isTeam(type.getFlags())) {
status.addFatalError(OTRefactoringCoreMessages.getString(str));
}
return status;
}
/*
* Make a best guess to find the primary type of a CU even if names do not
* match.
*/
private static IType robustFindPrimaryType(ICompilationUnit compUnit) {
IType type = compUnit.findPrimaryType();
if (type != null)
return type;
IType[] types;
try {
types = compUnit.getTypes();
if (types != null) {
for (IType type2 : types) {
if (Flags.isPublic(type2.getFlags()))
return type2;
}
if (types.length > 0)
return types[0];
}
} catch (JavaModelException e) {
// nothing useful found, return null below
}
return null;
}
/**
* Returns all role types contained in the given project and related
* projects.
*
* @param project
* the given project
* @param monitor
* the progress monitor
* @return an array of role types
*/
public static IOTType[] getAllRoleClasses(IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
OTSearchRequestor requestor = new OTSearchRequestor();
try {
SearchPattern rolePattern = OTSearchEngine.createRoleTypePattern(IJavaSearchConstants.TYPE, SearchPattern.R_EXACT_MATCH);
IJavaElement[] relevantProjects = getRelevantProjects(project);
IJavaSearchScope scope = OTSearchEngine.createOTSearchScope(relevantProjects, true);
OTSearchEngine engine = new OTSearchEngine();
engine.search(rolePattern, scope, requestor, monitor);
} catch (CoreException ex) {
throw new JavaModelException(ex);
}
return requestor.getOTTypes();
}
public static ArrayList<IRoleType> getAllRolesForBase(IType baseType) throws CoreException {
OTSearchEngine engine = new OTSearchEngine();
IJavaSearchScope searchScope = SearchEngine.createWorkspaceScope();
SearchPattern pattern = SearchPattern.createPattern(baseType, IJavaSearchConstants.PLAYEDBY_REFERENCES);
final ArrayList<IRoleType> roles = new ArrayList<IRoleType>();
if (pattern == null)
OTRefactoringPlugin.getInstance().getLog().log(new Status(Status.ERROR, OTRefactoringPlugin.PLUGIN_ID, "Error creating pattern")); //$NON-NLS-1$
else
engine.search(
pattern,
searchScope,
new SearchRequestor() {
public void acceptSearchMatch(SearchMatch match) throws CoreException
{
Object element = match.getElement();
if (element instanceof IType)
roles.add((IRoleType) OTModelManager.getOTElement((IType) element));
}
},
null);
return roles;
}
private static IJavaElement[] getRelevantProjects(IJavaProject srcProject) throws JavaModelException {
List<IJavaProject> relevantProjects = new ArrayList<IJavaProject>();
relevantProjects.add(srcProject); // this one is relevant for sure
IJavaProject[] allJavaProjects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
for (int idx = 0; idx < allJavaProjects.length; idx++) {
IJavaProject prj = allJavaProjects[idx];
if (prj.isOnClasspath(srcProject)) {
relevantProjects.add(prj);
}
}
return relevantProjects.toArray(new IJavaElement[relevantProjects.size()]);
}
/**
* Returns all bound base types of the given role types, that are declared
* by playedBy.
*
* @param roleTypes
* an array of IRoleTypes
* @return a list of bound base types
* @throws JavaModelException
*/
public static ArrayList<IType> getAllDeclaredBaseTypes(IOTType[] roleTypes) throws JavaModelException {
ArrayList<IType> baseTypes = new ArrayList<IType>();
for (int idx = 0; idx < roleTypes.length; idx++) {
// IRoleType roleType =
// (IRoleType)OTModelManager.getOTElement(roleTypes[idx]);
IRoleType roleType = (IRoleType) roleTypes[idx];
if (roleType.getBaseclassName() == null) {
continue;
}
IType baseType = roleType.getBaseClass();
if (baseType != null && !baseTypes.contains(baseType)) {
baseTypes.add(baseType);
}
}
return baseTypes;
}
public static IMethod[] hierarchyDeclaresMethodName(IProgressMonitor pm, IMethod method, String newName) throws CoreException {
Set<IMethod> result = new HashSet<IMethod>();
IType type = method.getDeclaringType();
ITypeHierarchy hier = type.newTypeHierarchy(pm);
IMethod foundMethod = Checks.findMethod(newName, method.getParameterTypes().length, false, type);
if (foundMethod != null) {
result.add(foundMethod);
}
IMethod[] foundInHierarchyClasses = classesDeclareMethodName(hier, Arrays.asList(hier.getAllClasses()), method, newName);
if (foundInHierarchyClasses != null) {
result.addAll(Arrays.asList(foundInHierarchyClasses));
}
IType[] implementingClasses = hier.getImplementingClasses(type);
IMethod[] foundInImplementingClasses = classesDeclareMethodName(hier, Arrays.asList(implementingClasses), method, newName);
if (foundInImplementingClasses != null) {
result.addAll(Arrays.asList(foundInImplementingClasses));
}
return result.toArray(new IMethod[result.size()]);
}
private static IMethod[] classesDeclareMethodName(ITypeHierarchy hier, List<IType> classes, IMethod method, String newName) throws CoreException {
Set<IMethod> result = new HashSet<IMethod>();
IType type = method.getDeclaringType();
List<IType> subtypes = Arrays.asList(hier.getAllSubtypes(type));
int parameterCount = method.getParameterTypes().length;
boolean isMethodPrivate = JdtFlags.isPrivate(method);
for (Iterator<IType> iter = classes.iterator(); iter.hasNext();) {
IType clazz = iter.next();
IMethod[] methods = clazz.getMethods();
boolean isSubclass = subtypes.contains(clazz);
for (int j = 0; j < methods.length; j++) {
IMethod foundMethod = Checks.findMethod(newName, parameterCount, false, new IMethod[] { methods[j] });
if (foundMethod == null) {
continue;
}
if (isSubclass || type.equals(clazz)) {
result.add(foundMethod);
} else if ((!isMethodPrivate) && (!JdtFlags.isPrivate(methods[j]))) {
result.add(foundMethod);
}
}
}
return result.toArray(new IMethod[result.size()]);
}
/**
* Checks if the given method is declared in an interface. If the method's
* declaring type is an interface the method returns <code>false</code> if
* it is only declared in that interface.
*/
public static IMethod isDeclaredInInterface(IMethod method, OTTypeHierarchy hierarchy, IProgressMonitor pm) throws JavaModelException {
assert isVirtual(method);
try {
IType[] classes = hierarchy.getAllClasses();
IProgressMonitor subPm = new SubProgressMonitor(pm, 3);
subPm.beginTask("", classes.length); //$NON-NLS-1$
for (int idxAllHierarchyClasses = 0; idxAllHierarchyClasses < classes.length; idxAllHierarchyClasses++) {
ITypeHierarchy superTypes = hierarchy.getOTSuperTypeHierarchy(classes[idxAllHierarchyClasses]);
IType[] superinterfaces = superTypes.getAllSuperInterfaces(classes[idxAllHierarchyClasses]);
for (int idxSuperInterfaces = 0; idxSuperInterfaces < superinterfaces.length; idxSuperInterfaces++) {
IMethod found = Checks.findSimilarMethod(method, superinterfaces[idxSuperInterfaces]);
if (found != null && !found.equals(method))
return found;
}
subPm.worked(1);
}
return null;
} finally {
pm.done();
}
}
public static boolean isVirtual(IMethod method) throws JavaModelException {
IType declaringType = method.getDeclaringType();
if (TypeHelper.isRole(declaringType.getFlags())) {
if (method.isConstructor())
return false;
// note: private role method is virtual
// if (JdtFlags.isPrivate(method))
// return false;
if (JdtFlags.isStatic(method))
return false;
} else {
if (method.isConstructor())
return false;
if (JdtFlags.isPrivate(method))
return false;
if (JdtFlags.isStatic(method))
return false;
}
return true;
}
public static IMethod overridesAnotherMethod(IMethod method, OTTypeHierarchy hier, IProgressMonitor pm) throws JavaModelException {
IType declaringType = method.getDeclaringType();
InheritedMethodsRequestor requestor = new InheritedMethodsRequestor(declaringType, true, true);
OTTypeHierarchyTraverser traverser = new OTTypeHierarchyTraverser(requestor, OTTypeHierarchyTraverser.SUPER_HIERARCHY,
OTTypeHierarchyTraverser.TRAVERSE_EXPLICIT_FIRST, false, false, pm);
traverser.traverse();
IMethod[] collectedMethods = requestor.getResult();
for (int idx = collectedMethods.length - 1; idx >= 0; idx--) {
if (method.isSimilar(collectedMethods[idx])) {
return collectedMethods[idx];
}
}
return null;
}
public static boolean isRoleMethod(IMethod method) throws JavaModelException {
IType type = method.getDeclaringType();
IOTType otType = OTModelManager.getOTElement(type);
if (otType == null) {
return false;
} else if (otType.isRole()) {
return true;
} else {
return false;
}
}
public static String stripOffJavaSuffix(String compUnit) {
int dot = compUnit.lastIndexOf('.');
return compUnit.substring(0, dot);
}
/**
* Returns the corresponding DOM-AST node for the given role type.
*
* @param role
* the given role type
* @return node of type RoleTypeDeclaration
* @throws JavaModelException
*/
public static RoleTypeDeclaration getRoleClassDeclaration(IMember role) throws JavaModelException {
ASTNode result = getASTNode(role, RoleTypeDeclaration.class);
return (RoleTypeDeclaration) result;
}
/**
* Returns the corresponding DOM-AST node for the given method.
*
* @param method
* the given method
* @return node of type MethodDeclaration
* @throws JavaModelException
*/
public static MethodDeclaration getMethodDeclaration(IMember method) throws JavaModelException {
ASTNode result = getASTNode(method, MethodDeclaration.class);
return (MethodDeclaration) result;
}
/**
* Determines the focus type, i.e. the destination type of the refactored
* element (e.g. the destination type for an extracted or moved method).
*
* @param topLevelType
* the top-level type of the destination compilation unit
* @param destinationType
* the destination type node
* @return the focus type, i.e. either a regular class (including team) or a
* role class
*/
public static IType determineFocusType(IType topLevelType, ASTNode destinationType) {
// if the destination of the extracted/moved code fragment/element is a
// role type,
// this role is the focus type...
if (destinationType instanceof RoleTypeDeclaration) {
RoleTypeDeclaration roleTypeDecl = (RoleTypeDeclaration) destinationType;
ITypeBinding roleTypeBinding = ASTNodes.getTypeBinding(roleTypeDecl.getName());
// if role is declared in the top-level type, get it...
if (roleTypeBinding != null) {
// Note: use String-based comparison for ITypeBinding <-> IType:
String topLevelName = topLevelType.getFullyQualifiedName();
String roleName = roleTypeBinding.getQualifiedName();
if (roleName.equals(topLevelName))
return topLevelType; // top level = focus (RoFi)
if (roleTypeBinding.getDeclaringClass().getQualifiedName().equals(topLevelName)) {
String simpleRoleName = roleTypeBinding.getName();
// role name very likely starts with __OT__, strip it off:
if (simpleRoleName.startsWith(IOTConstants.OT_DELIM))
simpleRoleName = simpleRoleName.substring(IOTConstants.OT_DELIM_LEN);
return TypeHelper.findRoleType(topLevelType, simpleRoleName);
}
// ...else find the nested role
else {
String relativeRoleName = getRelativeName(topLevelName, roleName);
return TypeHelper.findNestedRoleType(topLevelType, relativeRoleName);
}
}
return null;
}
// ...else the focus type is a team or regular class
else {
return topLevelType;
}
}
/**
* Make the given qualified name relative, so that the simple name or
* rootType is the first part of the resulting name.
*
* @param rootType
* @param fullyQualifiedName
* @return
*/
private static String getRelativeName(String rootType, String fullyQualifiedName) {
assert fullyQualifiedName.startsWith(rootType) : "role type must start like enclosing team"; //$NON-NLS-1$
int pos = rootType.lastIndexOf('.');
if (pos == -1)
pos = rootType.length();
return fullyQualifiedName.substring(pos + 1);
}
public static RefactoringStatus checkOverloading(IMethod[] inheritedMethods, String newName, String[] newParameterTypes, IOverloadingMessageCreator msgCreator) {
RefactoringStatus result = new RefactoringStatus();
for (int idx = 0; idx < inheritedMethods.length; idx++) {
// check if an inherited method or a local method has the
// same name as the method to be refactored
IMethod actualMethod = inheritedMethods[idx];
if (actualMethod.getElementName().equals(newName)) {
// get number of parameters of actual method
int actualMethodParamCount = actualMethod.getParameterTypes().length;
// get parameter types of actual method
String[] actualMethodParamTypes = getParameterTypesOfActualMethod(actualMethod);
// get number of parameters of method to be refactored
int refactoredMethodParamCount = newParameterTypes == null ? 0 : newParameterTypes.length;
// check if this method has a different number of parameters
// than
// the method to be refactored or...
if (actualMethodParamCount != refactoredMethodParamCount) {
// if overloading is present, issue a warning
result.merge(addOverloadingWarning(msgCreator));
}
// ...if it has the same number of parameters but different
// parameter types
else if (newParameterTypes != null) {
for (int idz = 0; idz < actualMethodParamTypes.length; idz++) {
if (!actualMethodParamTypes[idz].equals(newParameterTypes[idz])) {
// if overloading is present, issue a warning
result.merge(addOverloadingWarning(msgCreator));
}
}
}
}
}
return result;
}
private static String[] getParameterTypesOfActualMethod(IMethod actualMethod) {
String[] actualMethodParamTypes = actualMethod.getParameterTypes();
String[] readableActualMethodParamTypes = new String[actualMethodParamTypes.length];
for (int idy = 0; idy < actualMethodParamTypes.length; idy++) {
// convert parameter types into readable names
readableActualMethodParamTypes[idy] = Signature.toString(actualMethodParamTypes[idy]);
}
return readableActualMethodParamTypes;
}
@SuppressWarnings("unchecked")
// List getBaseMappingElements()
public static RefactoringStatus checkForAmbiguousBaseMethodSpecs(ArrayList<IRoleType> boundRoleTypes, String newMethodName, String oldMethodName, IAmbuguityMessageCreator msgCreator)
throws JavaModelException {
RefactoringStatus result = new RefactoringStatus();
for (Iterator<IRoleType> iter = boundRoleTypes.iterator(); iter.hasNext();) {
IRoleType boundRoleType = iter.next();
// get all method mappings of bound role type
AbstractMethodMappingDeclaration[] mappings = RefactoringUtil.getAllMethodMappings(boundRoleType);
if (mappings != null && mappings.length != 0) {
for (int idx = 0; idx < mappings.length; idx++) {
AbstractMethodMappingDeclaration mapping = mappings[idx];
if (mapping instanceof CallinMappingDeclaration) {
CallinMappingDeclaration callinDecl = (CallinMappingDeclaration) mapping;
List<MethodMappingElement> baseMethodSpecs = callinDecl.getBaseMappingElements();
for (Iterator<MethodMappingElement> iterator = baseMethodSpecs.iterator(); iterator.hasNext();) {
MethodMappingElement baseMethodSpec = iterator.next();
String baseMethodName = baseMethodSpec.getName().getIdentifier();
// check if base method specifier in callin mapping
// has
// no signature and if it has the same name as the
// extracted
// method
if (!baseMethodSpec.hasSignature() && (baseMethodName.equals(newMethodName) || baseMethodName.equals(oldMethodName))) {
// create the context
RefactoringStatusContext context = createContext(boundRoleType, baseMethodSpec);
// if it has the same name, issue an error
result.merge(addAmbiguityFatalError(context, msgCreator));
}
}
} else if (mapping instanceof CalloutMappingDeclaration) {
CalloutMappingDeclaration calloutDecl = (CalloutMappingDeclaration) mapping;
MethodMappingElement baseElement = calloutDecl.getBaseMappingElement();
// check if base element is a method spec and not a
// field access spec
if (baseElement instanceof MethodSpec) {
MethodSpec baseMethodSpec = (MethodSpec) baseElement;
String baseMethodName = baseMethodSpec.getName().getIdentifier();
// check if base method specifier in callout mapping
// has
// no signature and if it has the same name as the
// extracted
// method
if (!baseMethodSpec.hasSignature() && (baseMethodName.equals(newMethodName) || baseMethodName.equals(oldMethodName))) {
// create the context
RefactoringStatusContext context = createContext(boundRoleType, baseMethodSpec);
// if it has the same name, issue an error
result.merge(addAmbiguityFatalError(context, msgCreator));
}
}
}
}
}
}
return result;
}
public static RefactoringStatus checkForAmbiguousRoleMethodSpecs(IRoleType roleType, String newMethodName, IAmbuguityMessageCreator msgCreator) throws JavaModelException {
RefactoringStatus result = new RefactoringStatus();
// get all method mappings of role type
AbstractMethodMappingDeclaration[] mappings = RefactoringUtil.getAllMethodMappings(roleType);
if (mappings != null && mappings.length != 0) {
for (int idx = 0; idx < mappings.length; idx++) {
AbstractMethodMappingDeclaration mapping = mappings[idx];
if (mapping instanceof CallinMappingDeclaration) {
CallinMappingDeclaration callinDecl = (CallinMappingDeclaration) mapping;
MethodSpec roleMethodSpec = (MethodSpec) callinDecl.getRoleMappingElement();
String roleMethodName = roleMethodSpec.getName().getIdentifier();
// check if role method specifier in callin mapping has
// no signature and if it has the same name as the extracted
// method
if (!roleMethodSpec.hasSignature() && roleMethodName.equals(newMethodName)) {
// create the context
RefactoringStatusContext context = createContext(roleType, roleMethodSpec);
// if it has the same name, issue an error
result.merge(addAmbiguityFatalError(context, msgCreator));
}
} else if (mapping instanceof CalloutMappingDeclaration) {
CalloutMappingDeclaration calloutDecl = (CalloutMappingDeclaration) mapping;
MethodSpec roleMethodSpec = (MethodSpec) calloutDecl.getRoleMappingElement();
String roleMethodName = roleMethodSpec.getName().getIdentifier();
// check if role method specifier in callout mapping has
// no signature and if it has the same name as the extracted
// method
if (!roleMethodSpec.hasSignature() && roleMethodName.equals(newMethodName)) {
// create the context
RefactoringStatusContext context = createContext(roleType, roleMethodSpec);
// if it has the same name, issue an error
result.merge(addAmbiguityFatalError(context, msgCreator));
}
}
}
}
return result;
}
/**
* Returns all method mappings of the given role type.
*
* @param roleType
* the given role type
* @return an array of method mapping declarations
* @throws JavaModelException
*/
public static AbstractMethodMappingDeclaration[] getAllMethodMappings(IRoleType roleType) throws JavaModelException {
RoleTypeDeclaration roleClassDecl = getRoleClassDeclaration(roleType);
// get all callin and callout mappings of given role type
AbstractMethodMappingDeclaration[] callinMappings = roleClassDecl.getCallIns();
AbstractMethodMappingDeclaration[] calloutMappings = roleClassDecl.getCallOuts();
AbstractMethodMappingDeclaration[] mappings = new AbstractMethodMappingDeclaration[callinMappings.length + calloutMappings.length];
if (callinMappings.length != 0) {
System.arraycopy(callinMappings, 0, mappings, 0, callinMappings.length);
System.arraycopy(calloutMappings, 0, mappings, callinMappings.length, calloutMappings.length);
} else {
System.arraycopy(calloutMappings, 0, mappings, 0, calloutMappings.length);
}
return mappings;
}
public static RefactoringStatus addOverloadingWarning(IOverloadingMessageCreator msgCreator) {
RefactoringStatus result = RefactoringUtil.createWarningStatus(msgCreator.createOverloadingMessage(),
null, OTRefactoringStatusCodes.OVERLOADING);
return result;
}
public static RefactoringStatus addAmbiguityFatalError(RefactoringStatusContext context, IAmbuguityMessageCreator msgCreator) {
RefactoringStatus result = RefactoringUtil.createFatalErrorStatus(msgCreator.createAmbiguousMethodSpecifierMsg(),
context, OTRefactoringStatusCodes.AMBIGUOUS_METHOD_SPECIFIER);
return result;
}
/**
* Performs overloading checks for a team class or a regular class.
*
* @param result
* the actual refactoring status
* @param newMethodName
* the name of the refactored method
* @param focusType
* the destination type of the refactored method
* @param msgCreator a message creator object to provide refactoring specific error messages
* @param pm
* the progress monitor
* @param newMethod
* the refactored method
* @return the refactoring status containing a warning entry in case of
* overloading; ok otherwise.
* @throws JavaModelException
*/
public static RefactoringStatus checkOverloadingForTeamOrRegularClass(RefactoringStatus result, String newMethodName, String[] newParamTypes,
IType focusType, IOverloadingMessageCreator msgCreator, IProgressMonitor pm) throws JavaModelException {
RefactoringStatus status = new RefactoringStatus();
RefactoringStatusEntry overloading = result.getEntryMatchingCode(Corext.getPluginId(), OTRefactoringStatusCodes.OVERLOADING);
if (overloading == null) {
IMethod[] methods = TypeHelper.getInheritedMethods(focusType, true, true, true, pm);
status.merge(checkOverloading(methods, newMethodName, newParamTypes, msgCreator));
}
return status;
}
/**
* Performs overloading and ambiguity checks for a role type.
*
* @param result
* the actual refactoring status
* @param newMethodName
* the name of the refactored method
* @param roleType
* the focus role
* @param ambiguitymsgCreator a message creator object to provide refactoring specific error messages
* @param overloadingmsgCreator a message creator object to provide refactoring specific error messages
* @param pm
* the progress monitor
* @param newMethod
* the refactored method
* @return the refactoring status containing a warning entry in case of
* overloading, or a warning and fatal error entry in case of
* overloading and ambiguous method specs; ok otherwise.
* @throws JavaModelException
*/
public static RefactoringStatus checkOverloadingAndAmbiguityForRole(RefactoringStatus result, String newMethodName, String[] newParamTypes,
IRoleType roleType, IAmbuguityMessageCreator ambiguityMsgCreator, IOverloadingMessageCreator overloadingMsgCreator, IProgressMonitor pm) throws JavaModelException {
RefactoringStatus status = new RefactoringStatus();
RefactoringStatusEntry overloading = result.getEntryMatchingCode(Corext.getPluginId(), OTRefactoringStatusCodes.OVERLOADING);
if (overloading == null) {
// NOTE(gbr): result array of getInheritedMethods(..) also includes
// private methods. The reason is that method bindings may refer
// to hidden base methods (see OTJLD �3.4 and �4.6). This fact
// must be considered in the overloading and ambiguity checks.
IMethod[] methods = TypeHelper.getInheritedMethods(roleType, true, true, false, pm);
status.merge(checkOverloading(methods, newMethodName, newParamTypes, overloadingMsgCreator));
}
if (status.hasWarning() || result.hasWarning()) {
status.merge(checkForAmbiguousRoleMethodSpecs(roleType, newMethodName, ambiguityMsgCreator));
}
return status;
}
/**
* Performs overloading and ambiguity checks for a bound base type.
*
* @param result
* the actual refactoring status
* @param newMethodName
* the name of the refactored method
* @param oldMethodName
* the old name of the refactored method
* @param focusType
* the regarded type
* @param roleTypes
* the role types contained in the project
* @param ambiguitymsgCreator a message creator object to provide refactoring specific error messages
* @param overloadingmsgCreator a message creator object to provide refactoring specific error messages
* @param pm
* the progress monitor
* @param newMethod
* the refactored method
* @return the refactoring status containing a warning entry in case of
* overloading, or a warning and fatal error entry in case of
* overloading and ambiguous method specs; ok otherwise.
* @throws JavaModelException
*/
public static RefactoringStatus checkOverloadingAndAmbiguityForBase(RefactoringStatus result, String newMethodName, String oldMethodName,
String[] newParamTypes, IType focusType, IOTType[] roleTypes, IAmbuguityMessageCreator ambiguityMsgCreator, IOverloadingMessageCreator overloadingMsgCreator, IProgressMonitor pm) throws JavaModelException {
RefactoringStatus status = new RefactoringStatus();
ArrayList<IRoleType> boundRoleTypes = new ArrayList<IRoleType>();
for (int idx = 0; idx < roleTypes.length; idx++) {
IRoleType roleType = (IRoleType) roleTypes[idx];
IType baseClass = roleType.getBaseClass();
if (baseClass != null && baseClass.equals(focusType)) {
RefactoringStatusEntry overloadingThis = status.getEntryMatchingCode(Corext.getPluginId(), OTRefactoringStatusCodes.OVERLOADING);
RefactoringStatusEntry overloadingOther = result.getEntryMatchingCode(Corext.getPluginId(), OTRefactoringStatusCodes.OVERLOADING);
// check overloading only once for all role types bound to the
// same baseclass
if (overloadingThis == null && overloadingOther == null) {
// NOTE(gbr): result array of getInheritedMethods(..) also
// includes
// private methods. The reason is that method bindings may
// refer
// to hidden base methods (see OTJLD �3.4 and �4.6).
// This fact
// must be considered in the overloading and ambiguity
// checks.
IMethod[] baseMethods = TypeHelper.getInheritedMethods(baseClass, true, true, false, pm);
status.merge(checkOverloading(baseMethods, newMethodName, newParamTypes, overloadingMsgCreator));
}
// add role that is bound to the base class to the list
boundRoleTypes.add(roleType);
}
}
if (status.hasWarning() || result.hasWarning()) {
status.merge(checkForAmbiguousBaseMethodSpecs(boundRoleTypes, newMethodName, oldMethodName, ambiguityMsgCreator));
}
return status;
}
/**
* Performs overloading and ambiguity checks for a bound base type present
* in the super hierarchy of the focus (destination) type.
*
* @param newMethodName
* the name of the refactored method
* @param oldMethodName
* the old name of the refactored method
* @param superTypes
* the super types of the focus type
* @param msgCreator a message creator object to provide refactoring specific error messages
* @param roleType
* the role type bound to the base type
* @return the refactoring status containing a fatal error entry in case of
* ambiguous method specs; ok otherwise.
* @throws JavaModelException
*/
public static RefactoringStatus checkAmbiguityForBasePresentInFocusTypeSuperhierarchy(String newMethodName, String oldMethodName, IType[] superTypes,
IAmbuguityMessageCreator msgCreator, IRoleType roleType) throws JavaModelException {
RefactoringStatus status = new RefactoringStatus();
ArrayList<IRoleType> roleList = new ArrayList<IRoleType>();
IType baseClass = roleType.getBaseClass();
if (baseClass != null) {
for (int idx = 0; idx < superTypes.length; idx++) {
if (baseClass.equals(superTypes[idx])) {
roleList.add(roleType);
status.merge(checkForAmbiguousBaseMethodSpecs(roleList, newMethodName, oldMethodName, msgCreator));
}
}
}
return status;
}
/**
* Checks overloading and ambiguity for the given method name and method
* declaration.
*
* @param compUnit
* the target compilation unit
* @param destination
* the ast node representing the destination type
* @param newMethodName
* the name of the new method
* @param ambiguitymsgCreator a message creator object to provide refactoring specific error messages
* @param overloadingmsgCreator a message creator object to provide refactoring specific error messages
* @param pm
* the progress monitor
* @param newMethod
* the method declaration of the new method
* @return the refactoring status
* @throws JavaModelException
*/
public static RefactoringStatus checkOverloadingAndAmbiguity(ICompilationUnit compUnit, ASTNode destination, String newMethodName, String[] newParamTypes,
IAmbuguityMessageCreator ambiguityMsgCreator, IOverloadingMessageCreator overloadingMsgCreator, IProgressMonitor pm) throws JavaModelException {
// get top level type declared in compilation unit
IType topLevelType = robustFindPrimaryType(compUnit);
// determine focus type: can be either a regular class (including team)
// or a role
IType focusType = RefactoringUtil.determineFocusType(topLevelType, destination);
return checkOverloadingAndAmbiguity(focusType, null, newMethodName, newParamTypes, ambiguityMsgCreator, overloadingMsgCreator, pm);
}
/**
* Checks overloading and ambiguity for the given method name and method
* declaration.
*
* @param focusType
* the focus type to check for ambiguity
* @param focusTypeHierarchy
* the type hierarchy for the focus type - will be computed if
* <code>null</code>
* @param newMethodName
* the name of the new method
* @param newParamTypes
* the parameters of the new method
* @param ambigutiymsgCreator a message creator object to provide refactoring specific error messages
* @param overloadingmsgCreator a message creator object to provide refactoring specific error messages
* @param pm
* the progress monitor
* @return the refactoring status
* @throws JavaModelException
*/
public static RefactoringStatus checkOverloadingAndAmbiguity(IType focusType, ITypeHierarchy focusTypeHierarchy, String newMethodName,
String[] newParamTypes, IAmbuguityMessageCreator ambigutiyMsgCreator, IOverloadingMessageCreator overloadingMsgCreator, IProgressMonitor pm) throws JavaModelException {
ICompilationUnit compUnit = focusType.getCompilationUnit();
// create OT typehierarchy
if (focusTypeHierarchy == null) {
focusTypeHierarchy = new OTTypeHierarchy(focusType, compUnit.getJavaProject(), true);
focusTypeHierarchy.refresh(pm);
}
// get all supertypes of focus type
IType[] superTypes = focusTypeHierarchy.getAllSupertypes(focusType);
// get all subtypes of focus type
IType[] subTypes = focusTypeHierarchy.getAllSubtypes(focusType);
// get all role types in this project
// FIXME(SH): should replace gettingAllRoles with s.t. like RefactoringUtil.getAllRolesForBase(focusType);
IOTType[] roleTypes = RefactoringUtil.getAllRoleClasses(compUnit.getJavaProject(), pm);
// get all base types
ArrayList<IType> baseTypes = RefactoringUtil.getAllDeclaredBaseTypes(roleTypes);
RefactoringStatus result = new RefactoringStatus();
// if the focus type is a team,
// check for overloading methods in team and its supertypes
if (TypeHelper.isTeam(focusType.getFlags())) {
result.merge(RefactoringUtil.checkOverloadingForTeamOrRegularClass(result, newMethodName, newParamTypes, focusType, overloadingMsgCreator, pm));
if (result.getSeverity() == RefactoringStatus.WARNING) {
return result;
}
}
// if the focus type is a role,
// check for overloading methods in role and its supertypes,
// and for ambiguity in its method bindings
if (TypeHelper.isRole(focusType.getFlags())) {
IRoleType roleType = (IRoleType) OTModelManager.getOTElement(focusType);
result.merge(RefactoringUtil.checkOverloadingAndAmbiguityForRole(result, newMethodName, newParamTypes, roleType, ambigutiyMsgCreator, overloadingMsgCreator,
pm));
result.merge(RefactoringUtil.checkAmbiguityForBasePresentInFocusTypeSuperhierarchy(newMethodName, "", superTypes, ambigutiyMsgCreator, roleType));
}
// if the focus type is an unbound regular class,
// check for overloading methods in this class and its supertypes
else if (!baseTypes.contains(focusType)) {
RefactoringUtil.checkOverloadingForTeamOrRegularClass(result, newMethodName, newParamTypes, focusType, overloadingMsgCreator, pm);
if (result.getSeverity() == RefactoringStatus.WARNING) {
return result;
}
}
// if the focus type is a bound base class,
// check for overloading methods in this base class and its supertypes,
// and for ambiguity in method bindings of bound role classes
else if (baseTypes.contains(focusType)) {
result.merge(RefactoringUtil.checkOverloadingAndAmbiguityForBase(result, newMethodName, "", newParamTypes, focusType, roleTypes,
ambigutiyMsgCreator, overloadingMsgCreator, pm));
}
// if the focus type has subtypes,
// check overloading in the super hierarchy of each type
if (subTypes.length != 0) {
for (int idx = 0; idx < subTypes.length; idx++) {
IType subType = subTypes[idx];
// if the actual subtype of the focus type is a role,
// check for overloading methods in this role and its
// supertypes and for ambiguity in method bindings
if (TypeHelper.isRole(subType.getFlags())) {
IRoleType roleType = (IRoleType) OTModelManager.getOTElement(subType);
result.merge(RefactoringUtil.checkOverloadingAndAmbiguityForRole(result, newMethodName, newParamTypes, roleType, ambigutiyMsgCreator,
overloadingMsgCreator, pm));
if (result.hasWarning()) {
IType baseClass = roleType.getBaseClass();
ArrayList<IRoleType> roleList = new ArrayList<IRoleType>();
// if base class of role type is the focus type,
// check also ambiguous base method specs
if (baseClass != null && baseClass.equals(focusType)) {
roleList.add(roleType);
result.merge(RefactoringUtil.checkForAmbiguousBaseMethodSpecs(roleList, newMethodName, "", ambigutiyMsgCreator));
}
// else if base class of role type is a direct or
// indirect
// superclass of focus type, check also ambiguous base
// method specs
else {
result.merge(RefactoringUtil.checkAmbiguityForBasePresentInFocusTypeSuperhierarchy(newMethodName, "", superTypes, ambigutiyMsgCreator,
roleType));
}
}
}
// if the actual subtyp of the focus type is an unbound regular
// class,
// check for overloading methods in this class and its
// supertypes
else if (!baseTypes.contains(subType)) {
result.merge(RefactoringUtil
.checkOverloadingForTeamOrRegularClass(result, newMethodName, newParamTypes, subType, overloadingMsgCreator, pm));
}
// if the actual subtype of the focus type is a bound base
// class,
// check for overloading methods in this base class and its
// supertypes
// and for ambiguity in method bindings of bound role classes
else if (baseTypes.contains(subType)) {
result.merge(RefactoringUtil.checkOverloadingAndAmbiguityForBase(result, newMethodName, "", newParamTypes, subType, roleTypes, ambigutiyMsgCreator,
overloadingMsgCreator, pm));
}
}
}
return result;
}
// TODO(jsv): copy of checkOverloadingAndAmbiguity with ASTNode as
// destination -> remove redundant code
/**
* Checks overloading and ambiguity for the given method name and method
* declaration.
*
* @param compUnit
* the target compilation unit
* @param focusType
* the type of the renamed method
* @param newMethodName
* the name of the new method
* @param oldMethodName
* the old name of the method
* @param ambiguitymsgCreator a message creator object to provide refactoring specific error messages
* @param overloadingmsgCreator a message creator object to provide refactoring specific error messages.
* @param pm
* the progress monitor
* @param newMethod
* the IMethod of the new method
* @return the refactoring status
* @throws JavaModelException
*/
public static RefactoringStatus checkOverloadingAndAmbiguity(ICompilationUnit compUnit, IType focusType, String newMethodName, String oldMethodName,
String[] newParamTypes, IAmbuguityMessageCreator ambiguityMsgCreator, IOverloadingMessageCreator overloadingMsgCreator, IProgressMonitor pm) throws JavaModelException {
// FIXME(SH): what is this unused code good for?
// get top level type declared in compilation unit
// IType topLevelType = compUnit.findPrimaryType();
// determine focus type: can be either a regular class (including team)
// or a role
// IType focusType = RefactoringUtil.determineFocusType(topLevelType,
// destination);
// create OT typehierarchy
OTTypeHierarchy completeHierarchy = new OTTypeHierarchy(focusType, compUnit.getJavaProject(), true);
completeHierarchy.refresh(pm);
// get all supertypes of focus type
IType[] superTypes = completeHierarchy.getAllSupertypes(focusType);
// get all subtypes of focus type
IType[] subTypes = completeHierarchy.getAllSubtypes(focusType);
// get all role types in this project
// FIXME(SH): should replace gettingAllRoles with s.t. like RefactoringUtil.getAllRolesForBase(focusType);
IOTType[] roleTypes = RefactoringUtil.getAllRoleClasses(compUnit.getJavaProject(), pm);
// get all base types
ArrayList<IType> baseTypes = RefactoringUtil.getAllDeclaredBaseTypes(roleTypes);
RefactoringStatus result = new RefactoringStatus();
// if the focus type is a team,
// check for overloading methods in team and its supertypes
if (TypeHelper.isTeam(focusType.getFlags())) {
result.merge(RefactoringUtil.checkOverloadingForTeamOrRegularClass(result, newMethodName, newParamTypes, focusType, overloadingMsgCreator, pm));
if (result.getSeverity() == RefactoringStatus.WARNING) {
return result;
}
}
// if the focus type is a role,
// check for overloading methods in role and its supertypes,
// and for ambiguity in its method bindings
if (TypeHelper.isRole(focusType.getFlags())) {
IRoleType roleType = (IRoleType) OTModelManager.getOTElement(focusType);
result.merge(RefactoringUtil.checkOverloadingAndAmbiguityForRole(result, newMethodName, newParamTypes, roleType, ambiguityMsgCreator, overloadingMsgCreator,
pm));
result.merge(RefactoringUtil.checkAmbiguityForBasePresentInFocusTypeSuperhierarchy(newMethodName, oldMethodName, superTypes, ambiguityMsgCreator, roleType));
}
// if the focus type is an unbound regular class,
// check for overloading methods in this class and its supertypes
else if (!baseTypes.contains(focusType)) {
RefactoringUtil.checkOverloadingForTeamOrRegularClass(result, newMethodName, newParamTypes, focusType, overloadingMsgCreator, pm);
if (result.getSeverity() == RefactoringStatus.WARNING) {
return result;
}
}
// if the focus type is a bound base class,
// check for overloading methods in this base class and its supertypes,
// and for ambiguity in method bindings of bound role classes
else if (baseTypes.contains(focusType)) {
result.merge(RefactoringUtil.checkOverloadingAndAmbiguityForBase(result, newMethodName, oldMethodName, newParamTypes, focusType, roleTypes,
ambiguityMsgCreator, overloadingMsgCreator, pm));
}
// if the focus type has subtypes,
// check overloading in the super hierarchy of each type
if (subTypes.length != 0) {
for (int idx = 0; idx < subTypes.length; idx++) {
IType subType = subTypes[idx];
// if the actual subtype of the focus type is a role,
// check for overloading methods in this role and its
// supertypes and for ambiguity in method bindings
if (TypeHelper.isRole(subType.getFlags())) {
IRoleType roleType = (IRoleType) OTModelManager.getOTElement(subType);
result.merge(RefactoringUtil.checkOverloadingAndAmbiguityForRole(result, newMethodName, newParamTypes, roleType, ambiguityMsgCreator,
overloadingMsgCreator, pm));
if (result.hasWarning()) {
IType baseClass = roleType.getBaseClass();
ArrayList<IRoleType> roleList = new ArrayList<IRoleType>();
// if base class of role type is the focus type,
// check also ambiguous base method specs
if (baseClass != null && baseClass.equals(focusType)) {
roleList.add(roleType);
result.merge(RefactoringUtil.checkForAmbiguousBaseMethodSpecs(roleList, newMethodName, oldMethodName, ambiguityMsgCreator));
}
// else if base class of role type is a direct or
// indirect
// superclass of focus type, check also ambiguous base
// method specs
else {
result.merge(RefactoringUtil.checkAmbiguityForBasePresentInFocusTypeSuperhierarchy(newMethodName, oldMethodName, superTypes,
ambiguityMsgCreator, roleType));
}
}
}
// if the actual subtyp of the focus type is an unbound regular
// class,
// check for overloading methods in this class and its
// supertypes
else if (!baseTypes.contains(subType)) {
result.merge(RefactoringUtil
.checkOverloadingForTeamOrRegularClass(result, newMethodName, newParamTypes, subType, overloadingMsgCreator, pm));
}
// if the actual subtype of the focus type is a bound base
// class,
// check for overloading methods in this base class and its
// supertypes
// and for ambiguity in method bindings of bound role classes
else if (baseTypes.contains(subType)) {
result.merge(RefactoringUtil.checkOverloadingAndAmbiguityForBase(result, newMethodName, oldMethodName, newParamTypes, subType, roleTypes,
ambiguityMsgCreator, overloadingMsgCreator, pm));
}
}
}
return result;
}
/**
* Creates a refactoring status context for the given role type and method
* spec.
*
* @param roleType
* the role containing the error
* @param methodSpec
* the method spec that has caused the error
* @return the refactoring status context or null if the context cannot be
* created
*/
public static RefactoringStatusContext createContext(IRoleType roleType, MethodMappingElement methodSpec) {
RefactoringStatusContext context = JavaStatusContext.create(roleType.getCompilationUnit(), methodSpec);
return context;
}
/**
* Creates a warning refactoring status.
*
* @param msg
* the message of the warning entry
* @param context
* the context of the warning entry
* @param code
* the problem code (@see <code>OTRefactoringStatusCodes</code>)
* @return the refactoring status
*/
public static RefactoringStatus createWarningStatus(String msg, RefactoringStatusContext context, int code) {
return RefactoringStatus.createStatus(RefactoringStatus.WARNING, msg, context, Corext.getPluginId(), code, null);
}
/**
* Creates an error refactoring status.
*
* @param msg
* the message of the error entry
* @param context
* the context of the error entry
* @param code
* the problem code (@see <code>OTRefactoringStatusCodes</code>)
* @return the refactoring status
*/
public static RefactoringStatus createErrorStatus(String msg, RefactoringStatusContext context, int code) {
return RefactoringStatus.createStatus(RefactoringStatus.ERROR, msg, context, Corext.getPluginId(), code, null);
}
/**
* Creates a fatal error refactoring status.
*
* @param msg
* the message of the fatal error entry
* @param context
* the context of the fatal error entry
* @param code
* the problem code (@see <code>OTRefactoringStatusCodes</code>)
* @return the refactoring status
*/
public static RefactoringStatus createFatalErrorStatus(String msg, RefactoringStatusContext context, int code) {
return RefactoringStatus.createStatus(RefactoringStatus.FATAL, msg, context, Corext.getPluginId(), code, null);
}
/**
* Checks, if method has a special OT name. Does not use the
* OTTypeHIerarchy, because of performance optimization (team constants are
* using)
*
* @param current
* method to check
* @param new method name, should be <code>null</code> or an empty String if
* you wants to check the current method and not the new method with
* the same arguments like the current method
* @return the refactoring status
*/
public static boolean isOTSpecialCase(IMethod origMethod, String newMethodName, boolean checkImplementingClasses, IProgressMonitor pm) throws CoreException {
// TODO(jsv) what to do in case of interface is only used by base
// class(es) ? to check the impolementing classes is a performance
// overhead
IType declaringType = origMethod.getDeclaringType();
if (!Flags.isTeam(declaringType.getFlags())) {
// heavyweight check for interfaces
if (Flags.isInterface(declaringType.getFlags()) && checkImplementingClasses) {
OTTypeHierarchy hier = new OTTypeHierarchy(declaringType, declaringType.getJavaProject(), true);
hier.refresh(pm);
IType[] impementingClasses = hier.getImplementingClasses(declaringType);
boolean teamImplementsInterface = false;
for (int idx = 0; idx < impementingClasses.length; idx++) {
if (Flags.isTeam(impementingClasses[idx].getFlags())) {
teamImplementsInterface = true;
break;
}
}
if (!teamImplementsInterface) {
return false;
}
} else {
return false;
}
}
if (newMethodName == null || newMethodName.length() == 0)
newMethodName = origMethod.getElementName();
assert (virtualTeamMethodNames.length == virtualTeamMethodParamTypes.length)
&& (virtualTeamMethodParamTypes.length == virtualTeamMethodReturnTypes.length);
for (int i = 0; i < virtualTeamMethodNames.length; i++) {
if (virtualTeamMethodNames[i].equals(newMethodName) && Checks.compareParamTypes(origMethod.getParameterTypes(), virtualTeamMethodParamTypes[i])
&& virtualTeamMethodReturnTypes[i].equals(origMethod.getReturnType())) {
return true;
}
}
return false;
}
public static ASTNode getASTNode(IMember member, Class<? extends ASTNode> nodeClass) {
if (member == null || member.getCompilationUnit() == null) {
return null;
}
ICompilationUnit source = member.getCompilationUnit();
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setSource(source);
parser.setResolveBindings(true);
CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
// NOTE(SH): cannot use member.getSourceRange() together with the AST:
// member uses declarationSourceEnd (incl. comment) whereas
// the ASTConverter uses bodyEnd instead (excluding comment/trailing
// '}')
// However, getNameRange() should be safe.
try {
ASTNode name = NodeFinder.perform(astRoot, member.getNameRange());
return getParent(name, nodeClass);
} catch (JavaModelException e) {
return null;
}
}
/**
* Finds all overridden methods of a certain method.
*
*/
public static IMethod[] getOverriddenMethods(IMethod method, IProgressMonitor monitor) throws CoreException {
assert method != null;
return RippleMethodFinder2.getRelatedMethods(method, monitor, null);
}
/**
* Locates the topmost method of an override ripple and returns it. If none
* is found, null is returned.
*
* @param method
* the IMethod which may be part of a ripple
* @param typeHierarchy
* a ITypeHierarchy of the declaring type of the method. May be
* null
* @param monitor
* an IProgressMonitor
* @return the topmost method of the ripple, or null if none
* @throws JavaModelException
*/
public static IMethod getTopmostMethod(IMethod method, ITypeHierarchy typeHierarchy, IProgressMonitor monitor) throws JavaModelException {
assert method != null;
ITypeHierarchy hierarchy = typeHierarchy;
IMethod topmostMethod = null;
final IType declaringType = method.getDeclaringType();
if (!declaringType.isInterface()) {
if ((hierarchy == null) || !declaringType.equals(hierarchy.getType())) {
hierarchy = new OTTypeHierarchy(declaringType, declaringType.getJavaProject(), false);
hierarchy.refresh(monitor);
}
if (hierarchy instanceof OTTypeHierarchy) {
IMethod inInterface = isDeclaredInInterface(method, (OTTypeHierarchy) hierarchy, monitor);
if (inInterface != null && !inInterface.equals(method))
topmostMethod = inInterface;
}
}
if (topmostMethod == null) {
if (hierarchy == null) {
hierarchy = new OTTypeHierarchy(declaringType, declaringType.getJavaProject(), false);
hierarchy.refresh(monitor);
}
if (hierarchy instanceof OTTypeHierarchy) {
IMethod overrides = overridesAnotherMethod(method, (OTTypeHierarchy) hierarchy, monitor);
if (overrides != null && !overrides.equals(method))
topmostMethod = overrides;
}
}
return topmostMethod;
}
public static IField fieldIsShadowedInType(String elementName, String typeSignature, IType type) throws JavaModelException {
IField field = type.getField(elementName);
if (field.exists() && !field.getTypeSignature().equals(typeSignature)) {
return field;
}
return null;
}
public static MethodDeclaration methodToDeclaration(IMethod method, CompilationUnit node) throws JavaModelException {
ICompilationUnit methodCU = (ICompilationUnit) method.getAncestor(IJavaElement.COMPILATION_UNIT);
if (!methodCU.equals(node.getJavaElement())) {
node = RefactoringASTParser.parseWithASTProvider(methodCU, true, null);
}
Name result = (Name) NodeFinder.perform(node, method.getNameRange());
return (MethodDeclaration) getParent(result, MethodDeclaration.class);
}
public static AbstractMethodMappingDeclaration methodMappingToDeclaration(IMethodMapping methodMapping, CompilationUnit node) throws JavaModelException {
Name result = (Name) NodeFinder.perform(node, methodMapping.getNameRange());
return (AbstractMethodMappingDeclaration) getParent(result, AbstractMethodMappingDeclaration.class);
}
public static RefactoringStatus createNotYetFullyOTAwareMsg(String refactoringName) {
return RefactoringStatus.createInfoStatus(Messages.format("The ''{0}'' Refactoring is not yet fully OT-aware!", new Object[] { refactoringName }));
}
@SuppressWarnings("rawtypes")
private static ASTNode getParent(ASTNode node, Class parentClass) {
do {
node = node.getParent();
} while (node != null && !parentClass.isInstance(node));
return node;
}
public static ASTNode typeToDeclaration(IType type, CompilationUnit node) throws JavaModelException {
Name result = (Name) NodeFinder.perform(node, type.getNameRange());
if (type.isAnonymous())
return getParent(result, AnonymousClassDeclaration.class);
return getParent(result, AbstractTypeDeclaration.class);
}
public static RefactoringStatus checkForExistingRoles(String refactoringName,
IJavaProject project, IProgressMonitor pm) {
try {
if(project == null){
return createNotYetFullyOTAwareMsg(refactoringName);
}
if(getAllRoleClasses(project, pm).length > 0){
return createNotYetFullyOTAwareMsg(refactoringName);
}
} catch (JavaModelException e) {
return createNotYetFullyOTAwareMsg(refactoringName);
}
return new RefactoringStatus();
}
}