001: package spoon.vsuite.findbugs.dls;
002:
003: import spoon.processing.AbstractProblemFixer;
004: import spoon.processing.AbstractProcessor;
005: import spoon.processing.Property;
006: import spoon.processing.Severity;
007: import spoon.reflect.Changes;
008: import spoon.reflect.code.CtAssignment;
009: import spoon.reflect.code.CtExpression;
010: import spoon.reflect.code.CtFieldAccess;
011: import spoon.reflect.code.CtUnaryOperator;
012: import spoon.reflect.code.CtVariableAccess;
013: import spoon.reflect.code.UnaryOperatorKind;
014: import spoon.reflect.declaration.CtElement;
015: import spoon.reflect.declaration.CtVariable;
016: import spoon.reflect.visitor.CtScanner;
017:
018: /**
019: * DLS: Overwritten increment (DLS_OVERWRITTEN_INCREMENT). The code performs an
020: * increment operation (e.g., i++) and then immediately overwrites it. For
021: * example, i = i++ immediately overwrites the incremented value with the
022: * original value.
023: *
024: * @author Nicolas Petitprez
025: *
026: */
027:
028: public class OverwrittenIncrement extends
029: AbstractProcessor<CtAssignment<?, ?>> {
030:
031: public class Fixer1 extends
032: AbstractProblemFixer<CtAssignment<?, ?>> {
033: public String getDescription() {
034: return "Replace the unused increment by a variable access";
035: }
036:
037: public String getLabel() {
038: return "Remove increment";
039: }
040:
041: public Changes run(CtAssignment<?, ?> arg0) {
042: CtUnaryOperator<?> op = new IncrementScanner()
043: .getUnaryOperator(arg0);
044: op.replace(op.getOperand());
045:
046: Changes mod = new Changes();
047: mod.getModified().add(arg0);
048: return mod;
049: }
050:
051: }
052:
053: public class Fixer2 extends
054: AbstractProblemFixer<CtAssignment<?, ?>> {
055: public String getDescription() {
056: return "Replace the post increment by a pre-increment";
057: }
058:
059: public String getLabel() {
060: return "Replace increment";
061: }
062:
063: public Changes run(CtAssignment<?, ?> arg0) {
064: CtUnaryOperator<?> op = new IncrementScanner()
065: .getUnaryOperator(arg0);
066:
067: switch (op.getKind()) {
068: case POSTINC:
069: op.setKind(UnaryOperatorKind.PREINC);
070: break;
071: case POSTDEC:
072: op.setKind(UnaryOperatorKind.PREDEC);
073: break;
074: }
075:
076: Changes mod = new Changes();
077: mod.getModified().add(arg0);
078: return mod;
079: }
080: }
081:
082: @Property
083: static Severity level = Severity.WARNING;
084:
085: private class IncrementScanner extends CtScanner {
086:
087: CtVariable<?> variable;
088:
089: CtUnaryOperator<?> operator;
090:
091: public CtVariable<?> getUnaryOperatorVariable(CtElement e) {
092: scan(e);
093: return variable;
094: }
095:
096: public CtUnaryOperator<?> getUnaryOperator(CtElement e) {
097: scan(e);
098: return operator;
099: }
100:
101: @Override
102: public <T> void visitCtUnaryOperator(CtUnaryOperator<T> arg0) {
103: if (arg0.getKind() == UnaryOperatorKind.POSTDEC
104: || arg0.getKind() == UnaryOperatorKind.POSTINC) {
105: CtExpression<?> e = arg0.getOperand();
106: variable = new VariableScanner().getVariable(e);
107: operator = arg0;
108: }
109: super .visitCtUnaryOperator(arg0);
110: }
111: }
112:
113: private class VariableScanner extends CtScanner {
114:
115: CtVariable<?> variable;
116:
117: public CtVariable<?> getVariable(CtElement e) {
118: scan(e);
119: return variable;
120: }
121:
122: @Override
123: public <T> void visitCtVariableAccess(CtVariableAccess<T> arg0) {
124: super .visitCtVariableAccess(arg0);
125: variable = arg0.getVariable().getDeclaration();
126: }
127:
128: @Override
129: public <T> void visitCtFieldAccess(CtFieldAccess<T> fieldAccess) {
130: super .visitCtFieldAccess(fieldAccess);
131: variable = fieldAccess.getVariable().getDeclaration();
132: }
133: }
134:
135: public void process(CtAssignment<?, ?> arg0) {
136: // search assignment inc
137: CtVariable<?> assignment = new IncrementScanner()
138: .getUnaryOperatorVariable(arg0.getAssignment());
139:
140: if (assignment != null) {
141: // Getting assigned variable
142: CtVariable<?> assigned = new VariableScanner()
143: .getVariable(arg0.getAssigned());
144: if (assignment == assigned) {
145: getFactory().getEnvironment().report(this , level, arg0,
146: "Overwritten increment", new Fixer1(),
147: new Fixer2());
148: }
149: }
150: }
151:
152: }
|