]> git.uio.no Git - ifi-stolz-refaktor.git/blobdiff - case-study/refaktor-after/src/no/uio/ifi/refaktor/change/executors/MoveMethodRefactoringTargetFinder.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / refaktor-after / src / no / uio / ifi / refaktor / change / executors / MoveMethodRefactoringTargetFinder.java
diff --git a/case-study/refaktor-after/src/no/uio/ifi/refaktor/change/executors/MoveMethodRefactoringTargetFinder.java b/case-study/refaktor-after/src/no/uio/ifi/refaktor/change/executors/MoveMethodRefactoringTargetFinder.java
new file mode 100644 (file)
index 0000000..a94efab
--- /dev/null
@@ -0,0 +1,99 @@
+package no.uio.ifi.refaktor.change.executors;
+
+import java.util.List;
+
+import no.uio.ifi.refaktor.change.exceptions.RefaktorChangerException;
+import no.uio.ifi.refaktor.change.exceptions.VariableBindingNullException;
+import no.uio.ifi.refaktor.utils.ParseUtils;
+import no.uio.ifi.refaktor.utils.RefaktorASTNodeSearchUtil;
+
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo;
+
+/**
+ * A class responsible for finding the actual target to move the given method.
+ * 
+ * It does so with the help of the original target found before a 
+ * method got extracted. If the original target is a field, then it 
+ * is used a the new target. If it is not, then this class must search
+ * through the method parameters for the new method to find a parameter
+ * that corresponds to the binding for the original target.
+ * 
+ * If no target is found after this, the there probably is an error in 
+ * the analysis, and an exception is thrown.
+ */
+@SuppressWarnings("restriction")
+class MoveMethodRefactoringTargetFinder {
+
+       private final IMethod method;
+       private final IVariableBinding originalTarget;
+       private final List<ParameterInfo> parameterInfos;
+
+       public MoveMethodRefactoringTargetFinder(IMethod method, IVariableBinding originalTarget, List<ParameterInfo> parameterInfos) {
+               this.method = method;
+               this.originalTarget = originalTarget;
+               this.parameterInfos = parameterInfos;
+       }
+
+       public IVariableBinding findTarget() throws JavaModelException, RefaktorChangerException {
+               if (originalTarget.isField())
+                       return originalTarget;
+
+               return searchMethodParametersForTarget();
+       }
+
+       private IVariableBinding searchMethodParametersForTarget() throws JavaModelException {
+               if (methodHasParameters()) {
+                       ParameterInfo parameterInfo = getParameterInfoWithOldBinding();
+                       MethodDeclaration node = RefaktorASTNodeSearchUtil.getMethodDeclarationNode(method, ParseUtils.parse(method.getCompilationUnit()));
+                       for (Object declaration: node.parameters()) {
+                               assert declaration instanceof SingleVariableDeclaration;
+                               IVariableBinding declarationBinding = ((SingleVariableDeclaration)declaration).resolveBinding();
+                               if (declarationBinding == null)
+                                       throw new VariableBindingNullException(this.getClass());
+
+                               if (declarationMatchesParameterInfo(declarationBinding, parameterInfo))
+                                       return declarationBinding;
+                       }
+               }
+               throw new GenericChangerException(this.getClass() + ": Could not find target for Move Method refactoring. Analysis probably wrong.");
+       }
+
+       private boolean methodHasParameters() throws JavaModelException {
+               return method.getParameters().length != 0;
+       }
+
+       private ParameterInfo getParameterInfoWithOldBinding() {
+               String originalTargetKey = originalTarget.getKey();
+
+               for (ParameterInfo parameterInfo: parameterInfos) {
+                       IVariableBinding parameterInfoOldBinding = parameterInfo.getOldBinding();
+                       assert parameterInfoOldBinding != null;
+                       if (parameterInfoOldBinding.getKey().equals(originalTargetKey))
+                               return parameterInfo;
+               }
+               assert false: "The algorithm for finding the target may be wrong. Or some part of the analysis.";
+               return null;
+       }
+
+       private boolean declarationMatchesParameterInfo(IVariableBinding declarationBinding, ParameterInfo parameterInfo) {
+               return hasMatchingTypes(declarationBinding, parameterInfo) && hasMatchingNames(declarationBinding, parameterInfo);
+       }
+
+       private boolean hasMatchingTypes(IVariableBinding declarationBinding, ParameterInfo parameterInfo) {
+               ITypeBinding declarationBindingType = declarationBinding.getType();
+               assert declarationBindingType != null;
+               ITypeBinding parameterInfoOldBindingType = parameterInfo.getOldBinding().getType();
+               assert parameterInfoOldBindingType != null;
+               return declarationBindingType.isEqualTo(parameterInfoOldBindingType);
+       }
+
+       private boolean hasMatchingNames(IVariableBinding declarationBinding, ParameterInfo parameterInfo) {
+               return declarationBinding.getName().equals(parameterInfo.getNewName());
+       }
+}
\ No newline at end of file