01: package spoon.vsuite.findbugs.cn;
02:
03: import java.util.List;
04:
05: import spoon.processing.AbstractProcessor;
06: import spoon.processing.Property;
07: import spoon.processing.Severity;
08: import spoon.reflect.code.CtFieldAccess;
09: import spoon.reflect.code.CtInvocation;
10: import spoon.reflect.declaration.CtMethod;
11: import spoon.reflect.declaration.ModifierKind;
12: import spoon.reflect.visitor.Query;
13: import spoon.reflect.visitor.filter.AbstractFilter;
14:
15: /**
16: * CN: clone method does not call super.clone() (CN_IDIOM_NO_SUPER_CALL) This
17: * class defines a clone() method that does not call super.clone(), and is not
18: * final. If this class ("A") is extended by a subclass ("B"), and the subclass
19: * B calls super.clone(), then it is likely that B's clone() method will return
20: * an object of type A, which violates the standard contract for clone(). If all
21: * clone() methods call super.clone(), then they are guaranteed to use
22: * Object.clone(), which always returns an object of the correct type.
23: *
24: * @author Nicolas Petitprez
25: */
26: public class IdiomNoSuperCall extends AbstractProcessor<CtMethod<?>> {
27:
28: class Filter extends AbstractFilter<CtInvocation<?>> {
29:
30: public Filter() {
31: super (CtInvocation.class);
32: }
33:
34: public boolean matches(CtInvocation<?> arg0) {
35: if (arg0.getExecutable().getSimpleName().equals("clone")
36: && arg0.getArguments().isEmpty()
37: && arg0.getTarget() instanceof CtFieldAccess
38: && ((CtFieldAccess<?>) arg0.getTarget())
39: .getVariable().getSimpleName().equals(
40: "super")) {
41: return true;
42: }
43: return false;
44: }
45: }
46:
47: @Property
48: Severity level = Severity.WARNING;
49:
50: public void process(CtMethod<?> method) {
51: if (method.getSimpleName().equals("clone")
52: && !method.hasModifier(ModifierKind.FINAL)) {
53: List<CtInvocation<?>> inv = Query.getElements(method
54: .getBody(), new Filter());
55: if (inv.isEmpty())
56: getEnvironment().report(this , level, method,
57: "clone method does not call super.clone()");
58: }
59: }
60:
61: }
|