001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.corext.refactoring.rename;
011:
012: import org.eclipse.core.runtime.Assert;
013: import org.eclipse.core.runtime.CoreException;
014: import org.eclipse.core.runtime.IProgressMonitor;
015: import org.eclipse.core.runtime.SubProgressMonitor;
016:
017: import org.eclipse.ltk.core.refactoring.RefactoringStatus;
018: import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
019:
020: import org.eclipse.jdt.core.IMethod;
021: import org.eclipse.jdt.core.IType;
022: import org.eclipse.jdt.core.ITypeHierarchy;
023: import org.eclipse.jdt.core.JavaModelException;
024: import org.eclipse.jdt.core.dom.IMethodBinding;
025: import org.eclipse.jdt.core.dom.Modifier;
026:
027: import org.eclipse.jdt.internal.corext.Corext;
028: import org.eclipse.jdt.internal.corext.refactoring.Checks;
029: import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
030: import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
031: import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes;
032: import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
033: import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
034: import org.eclipse.jdt.internal.corext.util.JdtFlags;
035: import org.eclipse.jdt.internal.corext.util.Messages;
036: import org.eclipse.jdt.internal.corext.util.MethodOverrideTester;
037:
038: public class MethodChecks {
039:
040: //no instances
041: private MethodChecks() {
042: }
043:
044: public static boolean isVirtual(IMethod method)
045: throws JavaModelException {
046: if (method.isConstructor())
047: return false;
048: if (JdtFlags.isPrivate(method))
049: return false;
050: if (JdtFlags.isStatic(method))
051: return false;
052: return true;
053: }
054:
055: public static boolean isVirtual(IMethodBinding methodBinding) {
056: if (methodBinding.isConstructor())
057: return false;
058: if (Modifier.isPrivate(methodBinding.getModifiers())) //TODO is this enough?
059: return false;
060: if (Modifier.isStatic(methodBinding.getModifiers())) //TODO is this enough?
061: return false;
062: return true;
063: }
064:
065: public static RefactoringStatus checkIfOverridesAnother(
066: IMethod method, ITypeHierarchy hierarchy)
067: throws JavaModelException {
068: IMethod overrides = MethodChecks.overridesAnotherMethod(method,
069: hierarchy);
070: if (overrides == null)
071: return null;
072:
073: RefactoringStatusContext context = JavaStatusContext
074: .create(overrides);
075: String message = Messages.format(
076: RefactoringCoreMessages.MethodChecks_overrides,
077: new String[] {
078: JavaElementUtil
079: .createMethodSignature(overrides),
080: JavaModelUtil.getFullyQualifiedName(overrides
081: .getDeclaringType()) });
082: return RefactoringStatus.createStatus(RefactoringStatus.FATAL,
083: message, context, Corext.getPluginId(),
084: RefactoringStatusCodes.OVERRIDES_ANOTHER_METHOD,
085: overrides);
086: }
087:
088: /**
089: * Checks if the given method is declared in an interface. If the method's declaring type
090: * is an interface the method returns <code>false</code> if it is only declared in that
091: * interface.
092: */
093: public static RefactoringStatus checkIfComesFromInterface(
094: IMethod method, ITypeHierarchy hierarchy,
095: IProgressMonitor monitor) throws JavaModelException {
096: IMethod inInterface = MethodChecks.isDeclaredInInterface(
097: method, hierarchy, monitor);
098:
099: if (inInterface == null)
100: return null;
101:
102: RefactoringStatusContext context = JavaStatusContext
103: .create(inInterface);
104: String message = Messages.format(
105: RefactoringCoreMessages.MethodChecks_implements ,
106: new String[] {
107: JavaElementUtil
108: .createMethodSignature(inInterface),
109: JavaModelUtil.getFullyQualifiedName(inInterface
110: .getDeclaringType()) });
111: return RefactoringStatus.createStatus(RefactoringStatus.FATAL,
112: message, context, Corext.getPluginId(),
113: RefactoringStatusCodes.METHOD_DECLARED_IN_INTERFACE,
114: inInterface);
115: }
116:
117: /**
118: * Checks if the given method is declared in an interface. If the method's declaring type
119: * is an interface the method returns <code>false</code> if it is only declared in that
120: * interface.
121: */
122: public static IMethod isDeclaredInInterface(IMethod method,
123: ITypeHierarchy hierarchy, IProgressMonitor monitor)
124: throws JavaModelException {
125: Assert.isTrue(isVirtual(method));
126: IProgressMonitor subMonitor = new SubProgressMonitor(monitor, 1);
127: try {
128: IType[] classes = hierarchy.getAllClasses();
129: subMonitor.beginTask("", classes.length); //$NON-NLS-1$
130: for (int i = 0; i < classes.length; i++) {
131: final IType clazz = classes[i];
132: IType[] super interfaces = null;
133: if (clazz.equals(hierarchy.getType()))
134: super interfaces = hierarchy
135: .getAllSuperInterfaces(clazz);
136: else
137: super interfaces = clazz.newSupertypeHierarchy(
138: new SubProgressMonitor(subMonitor, 1))
139: .getAllSuperInterfaces(clazz);
140: for (int j = 0; j < super interfaces.length; j++) {
141: IMethod found = Checks.findSimilarMethod(method,
142: super interfaces[j]);
143: if (found != null && !found.equals(method))
144: return found;
145: }
146: subMonitor.worked(1);
147: }
148: return null;
149: } finally {
150: subMonitor.done();
151: }
152: }
153:
154: public static IMethod overridesAnotherMethod(IMethod method,
155: ITypeHierarchy hierarchy) throws JavaModelException {
156: MethodOverrideTester tester = new MethodOverrideTester(method
157: .getDeclaringType(), hierarchy);
158: IMethod found = tester.findDeclaringMethod(method, true);
159: boolean overrides = (found != null && !found.equals(method)
160: && (!JdtFlags.isStatic(found)) && (!JdtFlags
161: .isPrivate(found)));
162: if (overrides)
163: return found;
164: else
165: return null;
166: }
167:
168: /**
169: * Locates the topmost method of an override ripple and returns it. If none
170: * is found, null is returned.
171: *
172: * @param method the IMethod which may be part of a ripple
173: * @param typeHierarchy a ITypeHierarchy of the declaring type of the method. May be null
174: * @param monitor an IProgressMonitor
175: * @return the topmost method of the ripple, or null if none
176: * @throws JavaModelException
177: */
178: public static IMethod getTopmostMethod(IMethod method,
179: ITypeHierarchy typeHierarchy, IProgressMonitor monitor)
180: throws JavaModelException {
181:
182: Assert.isNotNull(method);
183:
184: ITypeHierarchy hierarchy = typeHierarchy;
185: IMethod topmostMethod = null;
186: final IType declaringType = method.getDeclaringType();
187: if (!declaringType.isInterface()) {
188: if ((hierarchy == null)
189: || !declaringType.equals(hierarchy.getType()))
190: hierarchy = declaringType.newTypeHierarchy(monitor);
191:
192: IMethod inInterface = isDeclaredInInterface(method,
193: hierarchy, monitor);
194: if (inInterface != null && !inInterface.equals(method))
195: topmostMethod = inInterface;
196: }
197: if (topmostMethod == null) {
198: if (hierarchy == null)
199: hierarchy = declaringType
200: .newSupertypeHierarchy(monitor);
201: IMethod overrides = overridesAnotherMethod(method,
202: hierarchy);
203: if (overrides != null && !overrides.equals(method))
204: topmostMethod = overrides;
205: }
206: return topmostMethod;
207: }
208:
209: /**
210: * Finds all overridden methods of a certain method.
211: *
212: */
213: public static IMethod[] getOverriddenMethods(IMethod method,
214: IProgressMonitor monitor) throws CoreException {
215:
216: Assert.isNotNull(method);
217: return RippleMethodFinder2.getRelatedMethods(method, monitor,
218: null);
219: }
220: }
|