Index: .classpath
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.ui/.classpath,v
retrieving revision 1.31
diff -u -r1.31 .classpath
--- .classpath 7 May 2003 14:49:45 -0000 1.31
+++ .classpath 14 Aug 2003 17:05:05 -0000
@@ -1,9 +1,9 @@
-
-
-
-
+
+
+
+
@@ -14,9 +14,9 @@
-
+
+
-
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionDeclaredByCalledMethod.java
===================================================================
RCS file: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionDeclaredByCalledMethod.java
diff -N core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionDeclaredByCalledMethod.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionDeclaredByCalledMethod.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,47 @@
+package org.eclipse.jdt.internal.corext.refactoring.remove;
+
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+
+class ExceptionDeclaredByCalledMethod extends ExceptionOccurance {
+ private ITypeBinding fException;
+ private IMethodBinding fMethod;
+
+ public ITypeBinding getException() {
+ return fException;
+ }
+
+ public IMethodBinding getMethod() {
+ return fMethod;
+ }
+
+ public ExceptionDeclaredByCalledMethod(
+ ITypeBinding exception,
+ IMethodBinding method) {
+ fException = exception;
+ fMethod = method;
+ }
+
+ public int hashCode() {
+ return fException.hashCode() + fMethod.hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (o.getClass().equals(getClass())) {
+ ExceptionDeclaredByCalledMethod exceptionLocation =
+ (ExceptionDeclaredByCalledMethod) o;
+ if (exceptionLocation.fException.equals(fException)
+ && exceptionLocation.fMethod.equals(fMethod))
+ return true;
+ }
+ return false;
+ }
+
+ public String toString() {
+ return "Exception declared by Method:"
+ + getMethod().getDeclaringClass().getQualifiedName()
+ + "."
+ + getMethod().getName()
+ + "()";
+ }
+}
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionOccurance.java
===================================================================
RCS file: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionOccurance.java
diff -N core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionOccurance.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionOccurance.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,5 @@
+package org.eclipse.jdt.internal.corext.refactoring.remove;
+
+public class ExceptionOccurance {
+
+}
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionThrown.java
===================================================================
RCS file: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionThrown.java
diff -N core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionThrown.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/ExceptionThrown.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,4 @@
+package org.eclipse.jdt.internal.corext.refactoring.remove;
+
+public class ExceptionThrown extends ExceptionOccurance {
+}
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodMatcher.java
===================================================================
RCS file: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodMatcher.java
diff -N core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodMatcher.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodMatcher.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,37 @@
+/*
+ * Created on 24.07.2003
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.jdt.internal.corext.refactoring.remove;
+
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+
+
+class MethodMatcher extends ASTVisitor {
+
+ private MethodDeclaration fResult;
+ private IMethod fMethod;
+ MethodMatcher(IMethod method) {
+ fMethod = method;
+ }
+
+ public void endVisit(MethodDeclaration methodDeclaration) { // TODO bogus, care for different argument types, stop
+ // visits when fResult is set initially
+ if (methodDeclaration
+ .getName()
+ .toString()
+ .equals(fMethod.getElementName().toString())) {
+ RemoveRefactoring.log(this, "found " + fMethod.getElementName().toString());
+ fResult = methodDeclaration;
+ }
+ }
+
+ /** returns null
when no match is found */
+ MethodDeclaration getResult() {
+ return fResult;
+ }
+}
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodsExceptionUsageAnalysisResult.java
===================================================================
RCS file: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodsExceptionUsageAnalysisResult.java
diff -N core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodsExceptionUsageAnalysisResult.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodsExceptionUsageAnalysisResult.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,73 @@
+package org.eclipse.jdt.internal.corext.refactoring.remove;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jdt.core.IType;
+
+/**
+ * this method's exception usage analysis result is from the point of view of the method
+ * It a query/filter/holder only class.
+ *
+ */
+public class MethodsExceptionUsageAnalysisResult {
+ private IType fAnalyzedException;
+
+ private List exceptionsDeclaredByCalledMethods;
+
+ private boolean fExceptionThrown;
+ private boolean fExceptionDeclared;
+ private boolean fExceptionCaught;
+
+ public MethodsExceptionUsageAnalysisResult(IType analyzedException) {
+ fAnalyzedException = analyzedException;
+ exceptionsDeclaredByCalledMethods = new ArrayList(5);
+ }
+ public ExceptionDeclaredByCalledMethod[] getExceptionDeclaredByCalledMethods() {
+ return (
+ ExceptionDeclaredByCalledMethod[]) exceptionsDeclaredByCalledMethods
+ .toArray(
+ new ExceptionDeclaredByCalledMethod[exceptionsDeclaredByCalledMethods
+ .size()]);
+ }
+
+ public void add(ExceptionDeclaredByCalledMethod edbcm) {
+ exceptionsDeclaredByCalledMethods.add(edbcm);
+ }
+
+ void setExceptionThrown(boolean b) {
+ fExceptionThrown = b;
+ }
+ void setExceptionDeclared(boolean b) {
+ fExceptionDeclared = b;
+ }
+ void setExceptionCaught(boolean b) {
+ fExceptionCaught = b;
+ }
+ public boolean isExceptionCaught() {
+ return fExceptionCaught;
+ }
+ public boolean isExceptionDeclared() {
+ return fExceptionDeclared;
+ }
+ public boolean isExceptionThrown() {
+ return fExceptionThrown;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer("MethodsExceptionUsageResult:\n");
+ sb.append("\tthrows Exception=\t"+isExceptionThrown()+"\n");
+ sb.append("\tdeclares Exception=\t"+isExceptionDeclared()+"\n");
+ sb.append("\tcatches Exception=\t"+isExceptionCaught()+"\n");
+
+ sb.append("\tException declared by called methods:\n");
+ ExceptionDeclaredByCalledMethod[] exceptionDeclaredByCalledMethods = getExceptionDeclaredByCalledMethods();
+ for (int i = 0; i < exceptionDeclaredByCalledMethods.length; i++) {
+ sb.append("\t"+exceptionDeclaredByCalledMethods[i]+"\n");
+ }
+
+ return sb.toString();
+ }
+
+}
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodsExceptionUsageAnalyzer.java
===================================================================
RCS file: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodsExceptionUsageAnalyzer.java
diff -N core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodsExceptionUsageAnalyzer.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/MethodsExceptionUsageAnalyzer.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+//TODO rework, generalize and use existing ExceptionAnalyzer
+package org.eclipse.jdt.internal.corext.refactoring.remove;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
+import org.eclipse.jdt.core.dom.CatchClause;
+import org.eclipse.jdt.core.dom.ClassInstanceCreation;
+import org.eclipse.jdt.core.dom.ConstructorInvocation;
+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.SimpleName;
+import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
+import org.eclipse.jdt.core.dom.SuperMethodInvocation;
+import org.eclipse.jdt.core.dom.ThrowStatement;
+import org.eclipse.jdt.core.dom.TryStatement;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.internal.corext.Assert;
+import org.eclipse.jdt.internal.corext.dom.Bindings;
+import org.eclipse.jdt.internal.corext.dom.Selection;
+
+public class MethodsExceptionUsageAnalyzer extends ASTVisitor {
+
+ private Selection fSelection;
+ private List fCurrentExceptionOccurances;
+ private Stack fTryStack;
+ private IType fException;
+ private MethodsExceptionUsageAnalysisResult fResult;
+ private MethodDeclaration fMethod;
+
+ private static class ExceptionComparator implements Comparator {
+ public int compare(Object o1, Object o2) {
+ int d1 = getDepth((ITypeBinding) o1);
+ int d2 = getDepth((ITypeBinding) o2);
+ if (d1 < d2)
+ return 1;
+ if (d1 > d2)
+ return -1;
+ return 0;
+ }
+ private int getDepth(ITypeBinding binding) {
+ int result = 0;
+ while (binding != null) {
+ binding = binding.getSuperclass();
+ result++;
+ }
+ return result;
+ }
+ }
+
+ protected MethodsExceptionUsageAnalyzer(
+ Selection selection,
+ IType exception,
+ MethodsExceptionUsageAnalysisResult result,
+ MethodDeclaration method) {
+ Assert.isNotNull(selection);
+ fSelection = selection;
+ fTryStack = new Stack();
+ fCurrentExceptionOccurances = new ArrayList(1);
+ fTryStack.push(fCurrentExceptionOccurances);
+ fException = exception;
+ fResult = result;
+ fMethod = method;
+
+ }
+ // TODO Add type ExceptionUsageAnalyzerResult
+ public static MethodsExceptionUsageAnalysisResult perform(
+ IType exceptionToBeAnalyzed,
+ MethodDeclaration enclosingMethod,
+ Selection selection) {
+ MethodsExceptionUsageAnalysisResult result =
+ new MethodsExceptionUsageAnalysisResult(exceptionToBeAnalyzed);
+ MethodsExceptionUsageAnalyzer analyzer =
+ new MethodsExceptionUsageAnalyzer(
+ selection,
+ exceptionToBeAnalyzed,
+ result,
+ enclosingMethod);
+ enclosingMethod.accept(analyzer);
+ result.setExceptionDeclared(analyzer.isExceptionDeclared());
+ //if (getDeclaredException(exception, enclosingMethod) != null)
+ // addExceptionOccurance(getDeclaredException(exception, enclosingMethod));
+ //Collections.sort(exceptions, new ExceptionComparator()); TODO what for?
+ return result;
+ }
+
+ //TODO check for QualifiedNames too.
+ private boolean isExceptionDeclared() {
+ boolean result = false;
+ for (Iterator simpleNames = fMethod.thrownExceptions().iterator();
+ simpleNames.hasNext();
+ ) {
+ SimpleName simpleName = (SimpleName) simpleNames.next();
+ ITypeBinding typeBinding = simpleName.resolveTypeBinding();
+ if (isRelevantException(typeBinding)) {
+ result = true;
+ break;
+ }
+ }
+ return result;
+ }
+ private boolean isRelevantException(ITypeBinding exception) {
+ if (exception
+ .getQualifiedName()
+ .equals(fException.getFullyQualifiedName()))
+ return true;
+ return false;
+ }
+
+ public boolean visit(ThrowStatement node) {
+ ITypeBinding exception = node.getExpression().resolveTypeBinding();
+ if (!isSelected(node)
+ || exception == null
+ || Bindings.isRuntimeException(
+ exception)) // Safety net for null bindings when compiling fails.
+ return true;
+ // TODO check if runtime exceptions should really be excluded?!
+ fResult.setExceptionThrown(true);
+ return true;
+ }
+
+ public boolean visit(MethodInvocation node) {
+ if (!isSelected(node))
+ return false;
+ return handleExceptions(node.resolveMethodBinding(), node.getAST());
+ }
+
+ public boolean visit(SuperMethodInvocation node) {
+ if (!isSelected(node))
+ return false;
+ return handleExceptions(node.resolveMethodBinding(), node.getAST());
+ }
+
+ public boolean visit(ClassInstanceCreation node) {
+ if (!isSelected(node))
+ return false;
+ return handleExceptions(
+ node.resolveConstructorBinding(),
+ node.getAST());
+ }
+
+ public boolean visit(ConstructorInvocation node) {
+ if (!isSelected(node))
+ return false;
+ return handleExceptions(
+ node.resolveConstructorBinding(),
+ node.getAST());
+ }
+
+ public boolean visit(SuperConstructorInvocation node) {
+ if (!isSelected(node))
+ return false;
+ return handleExceptions(
+ node.resolveConstructorBinding(),
+ node.getAST());
+ }
+
+ private boolean handleExceptions(IMethodBinding binding, AST ast) {
+ if (binding == null)
+ return true;
+ ITypeBinding[] exceptions = binding.getExceptionTypes();
+ for (int i = 0; i < exceptions.length; i++) {
+ if (isRelevantException(exceptions[i]))
+ fResult.add(
+ new ExceptionDeclaredByCalledMethod(
+ exceptions[i],
+ binding));
+ }
+ return true;
+ }
+
+ private boolean isSelected(ASTNode node) {
+ return fSelection.getVisitSelectionMode(node) == Selection.SELECTED;
+ }
+ public boolean visit(TypeDeclaration node) { // Don't dive into a local type.
+ if (node.isLocalTypeDeclaration())
+ return false;
+ return true;
+ }
+ public boolean visit(AnonymousClassDeclaration node) {
+ // Don't dive into a local type.
+ return false;
+ }
+ public boolean visit(TryStatement node) {
+ fCurrentExceptionOccurances = new ArrayList(1);
+ fTryStack.push(fCurrentExceptionOccurances);
+ // visit try block
+ node.getBody().accept(this);
+ // Remove those exceptions that get catch by following catch blocks
+ List catchClauses = node.catchClauses();
+ if (!catchClauses.isEmpty())
+ handleCatchArguments(catchClauses);
+ List current = (List) fTryStack.pop();
+ fCurrentExceptionOccurances = (List) fTryStack.peek();
+ for (Iterator iter = current.iterator(); iter.hasNext();) {
+ //addException((ITypeBinding)iter.next();
+ throw new RuntimeException("Not implemented yet!");
+ // TODO need to walk the enclosed statements? Would the complier care for that?
+ } // visit catch and finally
+ for (Iterator iter = catchClauses.iterator(); iter.hasNext();) {
+ ((CatchClause) iter.next()).accept(this);
+ }
+ if (node.getFinally() != null)
+ node.getFinally().accept(this);
+ // return false. We have visited the body by ourselves.
+ return false;
+ }
+ protected void addExceptionOccurance(ExceptionOccurance exceptionOccurance) {
+ if (!fCurrentExceptionOccurances.contains(exceptionOccurance))
+ fCurrentExceptionOccurances.add(exceptionOccurance);
+ }
+ private void handleCatchArguments(List catchClauses) {
+ for (Iterator iter = catchClauses.iterator(); iter.hasNext();) {
+ CatchClause clause = (CatchClause) iter.next();
+ ITypeBinding catchTypeBinding =
+ clause.getException().getType().resolveBinding();
+ if (catchTypeBinding == null) // No correct type resolve.
+ continue;
+ for (Iterator exceptions =
+ new ArrayList(fCurrentExceptionOccurances).iterator();
+ exceptions.hasNext();
+ ) {
+ ITypeBinding throwTypeBinding =
+ (ITypeBinding) exceptions.next();
+ if (catches(catchTypeBinding, throwTypeBinding))
+ fCurrentExceptionOccurances.remove(throwTypeBinding);
+ }
+ }
+ }
+ private boolean catches(
+ ITypeBinding catchTypeBinding,
+ ITypeBinding throwTypeBinding) {
+ while (throwTypeBinding != null) {
+ if (throwTypeBinding == catchTypeBinding)
+ return true;
+ throwTypeBinding = throwTypeBinding.getSuperclass();
+ }
+ return false;
+ }
+}
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/Referrer.java
===================================================================
RCS file: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/Referrer.java
diff -N core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/Referrer.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/Referrer.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,202 @@
+/*
+ * Created on 24.07.2003
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.jdt.internal.corext.refactoring.remove;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.internal.corext.dom.ASTRewrite;
+import org.eclipse.jdt.internal.corext.dom.Selection;
+import org.eclipse.jdt.internal.corext.refactoring.base.IChange;
+import org.eclipse.jdt.internal.corext.refactoring.changes.TextChange;
+import org.eclipse.jdt.internal.corext.refactoring.changes.TextFileChange;
+import org.eclipse.jdt.internal.corext.refactoring.remove.RemoveRefactoring.ReferrersMap;
+import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
+import org.eclipse.jdt.internal.corext.textmanipulation.MultiTextEdit;
+import org.eclipse.jdt.internal.corext.textmanipulation.TextBuffer;
+import org.eclipse.jdt.internal.corext.textmanipulation.TextEdit;
+
+
+class Referrer {
+ private IType fReferencedType;
+ private IMethod fReferringMethod;
+ private CompilationUnit fASTCU;
+ private MethodDeclaration fMethodDeclaration;
+ private ReferrersMap fEnclosingReferrersMap;
+ private MethodsExceptionUsageAnalysisResult fResult;
+
+ Referrer(
+ IType referencedType,
+ IMethod enclosingElement,
+ ReferrersMap enclosingReferencesMap) {
+ fReferencedType = referencedType;
+ fReferringMethod = enclosingElement;
+ fEnclosingReferrersMap = enclosingReferencesMap;
+ analyzeMethod();
+ }
+
+ CompilationUnit getASTCU() {
+ if (fASTCU == null)
+ fASTCU =
+ AST.parseCompilationUnit(fReferringMethod.getCompilationUnit(), true);
+ return fASTCU;
+ }
+
+ ICompilationUnit getCompilationUnit() {
+ return fReferencedType.getCompilationUnit();
+ }
+
+ MethodDeclaration getReferringMethodDeclaration() {
+ //TODO remove me.
+ extractMethodDeclaration();
+ return fMethodDeclaration;
+ }
+
+ ReferrersMap getEnclosingReferenceMap() {
+ return fEnclosingReferrersMap;
+ }
+
+ private void analyzeMethod() {
+ analyzeExceptionUsage();
+ }
+
+ private void extractMethodDeclaration() {
+
+ // TODO true? challenge later
+ MethodMatcher mm = new MethodMatcher(fReferringMethod);
+ getASTCU().accept(mm);
+
+ fMethodDeclaration = mm.getResult();
+ }
+
+ private void analyzeExceptionUsage() {
+ // TOD look for a better name than occuredException
+ fResult =
+ MethodsExceptionUsageAnalyzer.perform(
+ fReferencedType,
+ getReferringMethodDeclaration(),
+ Selection.createFromStartLength(
+ fMethodDeclaration.getStartPosition(),
+ fMethodDeclaration.getLength()));
+ }
+
+ IMethod getReferringMethod() {
+ return fReferringMethod;
+ }
+ boolean isRemovalSafe() {
+ if (fResult.isExceptionCaught() || fResult.isExceptionThrown())
+ return false;
+
+ ExceptionDeclaredByCalledMethod[] edbcm =
+ fResult.getExceptionDeclaredByCalledMethods();
+ for (int i = 0; i < edbcm.length; i++) {
+ ExceptionDeclaredByCalledMethod method = edbcm[i];
+ Referrer calledMethod =
+ (Referrer) fEnclosingReferrersMap.get(
+ method.getMethod().getName());
+ // TODO replace getName() by real key. also look at
+ // at collectReferences
+ boolean isCalledMethodDeclaringTheExceptionAlsoAnObservedReferrer =
+ calledMethod != null;
+ if (!isCalledMethodDeclaringTheExceptionAlsoAnObservedReferrer)
+ return false;
+ else {
+ if (!calledMethod.isRemovalSafe()) {
+ RemoveRefactoring.log(
+ this,
+ "removal is unsafe, because of " + calledMethod);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ // TODO do in batch mode with all methods for that particular cu?
+ IChange rewriteThrowsClause(TextChangeManager changeManager) throws CoreException {
+ ICompilationUnit enclosingCU = getCompilationUnit();
+ //CompilationUnit cu = AST.parseCompilationUnit(enclosingCU, true);
+ CompilationUnit cu = getASTCU();
+ // TODO challenge true
+ ASTRewrite rewrite = new ASTRewrite(cu);
+ //ASTNodeDeleteUtil.markAsDeleted(new IMethod[] { method }, cu, rewrite);
+
+ //TODO move the whole method to Reference?!
+ MethodDeclaration existingMethodDeclaration = getReferringMethodDeclaration();
+ List thrownExceptions = existingMethodDeclaration.thrownExceptions();
+ for (Iterator allExceptions = thrownExceptions.iterator(); allExceptions.hasNext();) {
+ SimpleName simpleName = (SimpleName) allExceptions.next();
+ if (simpleName.toString().equals(fReferencedType.getElementName())) {
+ rewrite.markAsRemoved(simpleName);
+ }
+ }
+
+ TextBuffer textBuffer =
+ TextBuffer.create(enclosingCU.getBuffer().getContents());
+ TextEdit resultingEdits = new MultiTextEdit();
+ rewrite.rewriteNode(textBuffer, resultingEdits);
+
+ TextChange textChange = changeManager.get(enclosingCU);
+ // TODO what is that supposed to be good for?
+ if (textChange instanceof TextFileChange) {
+ TextFileChange tfc = (TextFileChange) textChange;
+ tfc.setSave(!enclosingCU.isWorkingCopy());
+ }
+ //TODO fix the descriptions
+ String message = "Remove exception from throws clause of " + existingMethodDeclaration.getName()+".";
+ textChange.addTextEdit(message, resultingEdits);
+ rewrite.removeModifications();
+ RemoveRefactoring.log(this, "resultingEdits="+resultingEdits.size());
+ return textChange;
+
+ }
+
+ public String toString() {
+ StringBuffer sb =
+ new StringBuffer(
+ "Reference: method="
+ + fReferringMethod.getDeclaringType().getFullyQualifiedName()
+ + "."
+ + fReferringMethod.getElementName()
+ + "()\n");
+ sb.append("exception usage=\n" + fResult + "\n");
+ sb.append("isRemovalSafe=\t" + isRemovalSafe() + "\n");
+ // sb.append("\traises Exceptions\n");
+ // sb.append("\tinvoking methods=\t\t");
+ // IMethodBinding[] methodsDependingOn = getMethodsDependingOn();
+ // for (int i = 0; i < methodsDependingOn.length; i++) {
+ // sb.append(methodsDependingOn[i].getName());
+ // if (i != methodsDependingOn.length - 1)
+ // sb.append(", ");
+ //
+ // sb.append("\tDeclared Exceptions=\t");
+ // for (int i = 0; i < fDeclaredExceptions.length; i++) {
+ // sb.append(fDeclaredExceptions[i].getQualifiedName());
+ // if (i != fDeclaredExceptions.length - 1)
+ // sb.append(", ");
+ // }
+ //
+ // sb.append("\n\tRaised Exceptions=\t\t");
+ // for (int i = 0; i < fRaisedExceptions.length; i++) {
+ // sb.append(fRaisedExceptions[i].getQualifiedName());
+ // if (i != fRaisedExceptions.length - 1)
+ // sb.append(", ");
+ // }
+
+ //}
+ // sb.append("\n\tsafe removal=\t\t\t" + isRemovalSafe());
+ //sb.append("\n");
+ return sb.toString();
+ }
+}
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/RemoveRefactoring.java
===================================================================
RCS file: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/RemoveRefactoring.java
diff -N core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/RemoveRefactoring.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/RemoveRefactoring.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,325 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+//TODO 2000?
+//TODO Check for subclasses of exception to be removed.
+package org.eclipse.jdt.internal.corext.refactoring.remove;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.internal.corext.Assert;
+import org.eclipse.jdt.internal.corext.dom.ASTRewrite;
+import org.eclipse.jdt.internal.corext.refactoring.Checks;
+import org.eclipse.jdt.internal.corext.refactoring.CompositeChange;
+import org.eclipse.jdt.internal.corext.refactoring.base.IChange;
+import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
+import org.eclipse.jdt.internal.corext.refactoring.base.Refactoring;
+import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatus;
+import org.eclipse.jdt.internal.corext.refactoring.changes.TextChange;
+import org.eclipse.jdt.internal.corext.refactoring.changes.TextFileChange;
+import org.eclipse.jdt.internal.corext.refactoring.reorg.ASTNodeDeleteUtil;
+import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
+import org.eclipse.jdt.internal.corext.textmanipulation.MultiTextEdit;
+import org.eclipse.jdt.internal.corext.textmanipulation.TextBuffer;
+import org.eclipse.jdt.internal.corext.textmanipulation.TextEdit;
+
+/**
+ * TODO describe me
+ */
+public class RemoveRefactoring extends Refactoring {
+
+ public static RemoveRefactoring create(IType type)
+ throws JavaModelException {
+ if (Checks.checkAvailability(type).hasFatalError()) {
+ // TODO challenge
+ log(RemoveRefactoring.class, "checkAvailabilty has fatal error.");
+ return null;
+ }
+ return new RemoveRefactoring(type);
+ }
+
+ public static void log(Object caller, String message) {
+ System.out.println(caller.getClass().getName() + ": " + message);
+ }
+ private TextChangeManager fChangeManager;
+ private IType fType;
+
+ private ReferrersMap fReferrersMap;
+ private RemoveRefactoring(IType type) {
+ fType = type;
+ fReferrersMap = new ReferrersMap();
+ fChangeManager = new TextChangeManager();
+ }
+
+ public RefactoringStatus checkActivation(IProgressMonitor pm)
+ throws JavaModelException {
+
+ log(this, "checkActivation::enter");
+
+ pm.beginTask("", 11); // TODO message
+ pm.setTaskName("Checking selected IType"); // TODO message
+
+ RefactoringStatus result = new RefactoringStatus();
+ //log(this, "type=" + fType);
+ validateTypeIsSubclassOfThrowable(
+ result,
+ new SubProgressMonitor(pm, 1));
+ log(this, "result.isOK()=" + result.isOK());
+ log(this, "result=" + result);
+ log(this, "checkActivation::exit");
+ pm.done();
+ return result;
+ }
+
+ public RefactoringStatus checkInput(IProgressMonitor pm)
+ throws JavaModelException {
+ log(this, "checkInput::enter");
+ RefactoringStatus result = new RefactoringStatus();
+ fChangeManager.clear();
+
+ pm.beginTask("", 1); // PM
+ pm.setTaskName("Checking input."); // TODO message
+
+ collectReferrers(new SubProgressMonitor(pm, 1));
+ int removedCount = 0;
+ for (Iterator referrers = fReferrersMap.values().iterator();
+ referrers.hasNext();
+ ) {
+ Referrer referrer = (Referrer) referrers.next();
+ log(this, "processing " + referrer + ".");
+ if (referrer.isRemovalSafe()) {
+ try {
+ log(this, "rewriting Throws Clause.");
+ referrer.rewriteThrowsClause(fChangeManager);
+ log(this, "rewriting Throws Clause done.");
+ removedCount++;
+ } catch (CoreException e) {
+ result.addFatalError(
+ "CoreException raised while removing method.",
+ JavaStatusContext.create(
+ referrer.getReferringMethod()));
+ }
+ }
+ }
+
+ log(this, "checkInput::" + fReferrersMap.size());
+ // check number of edits instead?
+ try {
+ if (fReferrersMap.size() == removedCount)
+ removeReferencedType(fChangeManager);
+ } catch (CoreException e) {
+ result.addFatalError(
+ "CoreException raised while removing method.",
+ JavaStatusContext.create(fType));
+ }
+ log(this, "checkInput::exit");
+ return result;
+ }
+
+ private TextChange removeReferencedType(TextChangeManager changeManager)
+ throws CoreException {
+ CompilationUnit cu =
+ AST.parseCompilationUnit(fType.getCompilationUnit(), true);
+ TypeMatcher typeMatcher = new TypeMatcher(fType);
+ cu.accept(typeMatcher);
+ TypeDeclaration typeDeclaration = typeMatcher.getResult();
+ ASTRewrite rewrite = new ASTRewrite(cu);
+ ASTNodeDeleteUtil.markAsDeleted(new IType[] { fType }, cu, rewrite);
+
+ TextBuffer textBuffer =
+ TextBuffer.create(
+ fType.getCompilationUnit().getBuffer().getContents());
+ TextEdit resultingEdits = new MultiTextEdit();
+ rewrite.rewriteNode(textBuffer, resultingEdits);
+
+ TextChange textChange = changeManager.get(fType.getCompilationUnit());
+ // TODO what is that supposed to be good for?
+ if (textChange instanceof TextFileChange) {
+ TextFileChange tfc = (TextFileChange) textChange;
+ tfc.setSave(!fType.getCompilationUnit().isWorkingCopy());
+ }
+ //TODO fix the descriptions
+ String message =
+ "Remove exception from throws clause of "
+ + fType.getElementName()
+ + ".";
+ textChange.addTextEdit(message, resultingEdits);
+ rewrite.removeModifications();
+ RemoveRefactoring.log(this, "resultingEdits=" + resultingEdits.size());
+ return textChange;
+
+ }
+
+ private void collectReferrers(final IProgressMonitor pm)
+ throws JavaModelException {
+ log(this, "collectReferences::enter");
+ pm.beginTask("", 5);
+ pm.setTaskName("Searching references"); // TODO
+
+ IJavaSearchResultCollector searchCollector =
+ new IJavaSearchResultCollector() {
+ public void aboutToStart() {
+ }
+
+ public void accept(
+ IResource resource,
+ int start,
+ int end,
+ IJavaElement enclosingElement,
+ int accuracy)
+ throws CoreException {
+ Assert.isTrue(
+ enclosingElement.getElementType() == IJavaElement.METHOD,
+ "Oops. Haven't expected anything, but a method.");
+ //TODO
+ addReference(
+ new Referrer(
+ fType,
+ (IMethod) enclosingElement,
+ fReferrersMap));
+ // TODO check for accuracy needed
+ }
+
+ private void addReference(Referrer reference) {
+ ReferrersMap referencesMap =
+ reference.getEnclosingReferenceMap();
+ if (referencesMap
+ .get(reference.getReferringMethod().getElementName())
+ == null)
+ referencesMap.put(
+ reference.getReferringMethod().getElementName(),
+ reference);
+ }
+
+ public void done() {
+ }
+
+ public IProgressMonitor getProgressMonitor() {
+ return pm;
+ }
+ };
+ new SearchEngine().search(
+ ResourcesPlugin.getWorkspace(),
+ fType,
+ IJavaSearchConstants.REFERENCES,
+ SearchEngine.createJavaSearchScope(
+ new IJavaElement[] { fType.getCompilationUnit()}),
+ searchCollector);
+ // TODO enlarge scope
+ log(this, "\n" + fReferrersMap.toString());
+ pm.done();
+ log(this, "collectReferences::exit");
+ }
+
+ public IChange createChange(IProgressMonitor pm)
+ throws JavaModelException {
+ log(this, "createChange::enter");
+ CompositeChange result = new CompositeChange(getName());
+
+ result.addAll(fChangeManager.getAllChanges());
+ log(this, "createChange::exit");
+ return result;
+ }
+
+ public String getName() {
+ // TODO
+ return "Remove (from getName())";
+ }
+ private void validateTypeIsSubclassOfThrowable(
+ final RefactoringStatus result,
+ final IProgressMonitor pm)
+ throws JavaModelException {
+ //String[] superTypesNames = type.getSuperInterfaceNames();
+ // if (superTypesNames.length == 0
+ // || !superTypesNames[superTypesNames.length
+ // - 1].equals("java.lang.Throwable"))
+ // result.addFatalError("Type does not extend Throwable");
+ // TODO provide real message
+ // TODO check the hierarchy, not just the immediate superclass
+ // TODO check qualified/simple
+ //if (!type.getSuperclassName().equals("java.lang.Exception"))
+ // result.addFatalError("Type does not extend Throwable");
+ //pm.worked(1);
+
+ IJavaSearchScope searchScope = SearchEngine.createHierarchyScope(fType);
+ new SearchEngine()
+ .search(ResourcesPlugin.getWorkspace(), "java.lang.Exception",
+ // TODO Why doesn't this work with Throwable?
+ IJavaSearchConstants.TYPE,
+ IJavaSearchConstants.REFERENCES,
+ searchScope,
+ new IJavaSearchResultCollector() {
+ boolean typeIsSubclassOfThrowable = false;
+ public void aboutToStart() {
+ //log(this, "aboutToStart");
+ }
+
+ public void accept(
+ IResource resource,
+ int start,
+ int end,
+ IJavaElement enclosingElement,
+ int accuracy)
+ throws CoreException {
+ typeIsSubclassOfThrowable = true;
+ //log(this, "accept");
+ }
+
+ public void done() {
+ if (!typeIsSubclassOfThrowable)
+ result.addFatalError(
+ fType.getElementName()
+ + " is not a subclass of java.lang.Throwable.");
+ // TODO rework literal.
+ //log(this, "done()");
+ }
+
+ public IProgressMonitor getProgressMonitor() {
+ return pm;
+ }
+ });
+
+ }
+ class ReferrersMap extends HashMap {
+ //TODO check other ways to implement the enclosing reference map
+ public String toString() {
+ StringBuffer sb =
+ new StringBuffer(
+ "ReferencesMap: (holding " + size() + " references)\n");
+ for (Iterator allReferences = values().iterator();
+ allReferences.hasNext();
+ ) {
+ Referrer reference = (Referrer) allReferences.next();
+ sb.append(reference + "\n");
+ }
+ return sb.toString();
+ }
+ }
+}
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/TypeMatcher.java
===================================================================
RCS file: core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/TypeMatcher.java
diff -N core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/TypeMatcher.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/remove/TypeMatcher.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,39 @@
+/*
+ * Created on 24.07.2003
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.jdt.internal.corext.refactoring.remove;
+
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+
+class TypeMatcher extends ASTVisitor {
+
+ private TypeDeclaration fResult;
+ private IType fType;
+
+ TypeMatcher(IType type) {
+ fType = type;
+ }
+
+ public void endVisit(TypeDeclaration typeDeclaration) { // TODO bogus, care for different argument types, stop
+ // visits when fResult is set initially
+ if (typeDeclaration
+ .getName()
+ .toString()
+ .equals(fType.getElementName().toString())) {
+ RemoveRefactoring.log(
+ this,
+ "found " + fType.getElementName().toString());
+ fResult = typeDeclaration;
+ }
+ }
+
+ /** returns null
when no match is found */
+ TypeDeclaration getResult() {
+ return fResult;
+ }
+}