001: package spoon.vsuite.findbugs.de;
002:
003: import java.util.ArrayList;
004: import java.util.List;
005:
006: import spoon.processing.AbstractProblemFixer;
007: import spoon.processing.AbstractProcessor;
008: import spoon.processing.ProblemFixer;
009: import spoon.reflect.Changes;
010: import spoon.reflect.code.CtCatch;
011: import spoon.reflect.code.CtStatement;
012: import spoon.reflect.code.CtStatementList;
013: import spoon.reflect.code.CtTry;
014: import spoon.reflect.declaration.CtExecutable;
015: import spoon.reflect.declaration.CtMethod;
016: import spoon.reflect.declaration.CtSimpleType;
017: import spoon.reflect.reference.CtTypeReference;
018: import spoon.template.Substitution;
019: import spoon.vsuite.findbugs.template.CatcherTemplate;
020:
021: public abstract class ExceptionAnalyse<T extends CtStatement> extends
022: AbstractProcessor<T> {
023:
024: public class AddCatch extends AbstractProblemFixer<T> {
025: CtTry cttry;
026:
027: public AddCatch(CtTry cttry) {
028: super ();
029: this .cttry = cttry;
030: }
031:
032: public String getDescription() {
033: return "add catcher in parent try block";
034: }
035:
036: public String getLabel() {
037: return "add Catcher";
038: }
039:
040: public Changes run(T arg0) {
041: Changes change = new Changes();
042:
043: // Getting catcher from template
044: CtMethod<?> templateMethod = getFactory().Template().get(
045: CatcherTemplate.class.getName()).getMethod(
046: "catcher", new CtTypeReference<?>[0]);
047: CtTry templateTry = (CtTry) templateMethod.getBody()
048: .getStatements().get(0);
049: CtCatch templateCatcher = templateTry.getCatchers().get(0);
050:
051: // Substitute it
052: for (CtTypeReference<? extends Throwable> type : getThrownExceptionForElement(arg0)) {
053: CatcherTemplate t = new CatcherTemplate(type);
054: templateCatcher = Substitution.substitute(arg0
055: .getParent(CtSimpleType.class), t,
056: templateCatcher);
057: cttry.getCatchers().add(templateCatcher);
058: }
059: change.getModified().add(cttry);
060:
061: return change;
062: }
063: }
064:
065: public class ThrowsFix extends AbstractProblemFixer<T> {
066:
067: public ThrowsFix() {
068: super ();
069: }
070:
071: public String getDescription() {
072: return "add throws declaration";
073: }
074:
075: public String getLabel() {
076: return "thrown Exception";
077: }
078:
079: public Changes run(T arg0) {
080: CtExecutable<?> exec = arg0.getParent(CtExecutable.class);
081: Changes change = new Changes();
082: for (CtTypeReference<? extends Throwable> ref : getUncaptured(arg0)) {
083: exec.getThrownTypes().add(ref);
084: }
085: change.getModified().add(exec);
086: return change;
087: }
088: }
089:
090: public class SurroundFix extends AbstractProblemFixer<T> {
091:
092: public String getDescription() {
093: return "Surround with try/catch block";
094: }
095:
096: public String getLabel() {
097: return "Surround";
098: }
099:
100: public Changes run(T arg0) {
101: Changes change = new Changes();
102:
103: // Getting try/catch from template
104: CtMethod<?> templateMethod = getFactory().Template().get(
105: CatcherTemplate.class.getName()).getMethod(
106: "catcher", new CtTypeReference<?>[0]);
107: CtTry templateTry = (CtTry) templateMethod.getBody()
108: .getStatements().get(0);
109:
110: // Insert try/catch
111: CtStatementList<?> lst = getFactory().Core()
112: .createStatementList();
113: lst.getStatements().add(arg0);
114: CatcherTemplate t = new CatcherTemplate(
115: getThrownExceptionForElement(arg0).get(0), lst);
116:
117: templateTry = Substitution.substitute(arg0
118: .getParent(CtSimpleType.class), t, templateTry);
119: arg0.replace(templateTry);
120:
121: // insert other catcher
122: AddCatch c = new AddCatch(templateTry);
123: c.setFactory(getFactory());
124: c.run(arg0);
125:
126: change.getModified().add(arg0);
127:
128: return change;
129: }
130: }
131:
132: /**
133: * Return the list of throwables exceptions for given element.
134: */
135: protected abstract List<CtTypeReference<? extends Throwable>> getThrownExceptionForElement(
136: T element);
137:
138: private boolean isCaptured(T throwner,
139: CtTypeReference<? extends Throwable> exception) {
140: // Check if exception is catch
141: CtTry cttry = throwner.getParent(CtTry.class);
142: if (cttry != null)
143: while (cttry != null) {
144: for (CtCatch catcher : cttry.getCatchers()) {
145: if (exception.isSubtypeOf(catcher.getParameter()
146: .getType())) {
147: return true;
148: }
149: }
150: cttry = cttry.getParent(CtTry.class);
151: }
152:
153: // If not, check if exception is thrown
154: CtExecutable<?> exe = throwner.getParent(CtExecutable.class);
155: if (exe != null) {
156: for (CtTypeReference<?> th : exe.getThrownTypes()) {
157: if (exception.isSubtypeOf(th)) {
158: return true;
159: }
160: }
161: }
162: return false;
163: }
164:
165: /**
166: * Create a list of possible fixer for given element.
167: */
168: public List<ProblemFixer<?>> getFixer(T element) {
169: List<ProblemFixer<?>> ret = new ArrayList<ProblemFixer<?>>();
170: ret.add(new ThrowsFix());
171: ret.add(new SurroundFix());
172: CtTry cttry = element.getParent(CtTry.class);
173: if (cttry != null) {
174: ret.add(new AddCatch(cttry));
175: }
176: return ret;
177: }
178:
179: /**
180: * Create list of all uncaptured exception.
181: */
182: public List<CtTypeReference<? extends Throwable>> getUncaptured(
183: T throwner) {
184: List<CtTypeReference<? extends Throwable>> thr = getThrownExceptionForElement(throwner);
185:
186: // If no thrown Exception, skip
187: if (thr == null || thr.isEmpty())
188: return null;
189:
190: List<CtTypeReference<? extends Throwable>> ret = new ArrayList<CtTypeReference<? extends Throwable>>();
191:
192: for (CtTypeReference<? extends Throwable> ex : thr) {
193: if (!isCaptured(throwner, ex)) {
194: ret.add(ex);
195: }
196: }
197:
198: return ret;
199: }
200: }
|