package com.aptana.rdt.internal.parser.warnings; import java.util.List; import org.jruby.ast.DefnNode; import org.jruby.ast.IfNode; import org.jruby.ast.LocalVarNode; import org.jruby.ast.NilImplicitNode; import org.jruby.ast.Node; import org.rubypeople.rdt.core.parser.warnings.RubyLintVisitor; import org.rubypeople.rdt.internal.core.util.ASTUtil; import com.aptana.rdt.AptanaRDTPlugin; import com.aptana.rdt.IProblem; public class ControlCouple extends RubyLintVisitor { private Node condition; private List<String> args; private boolean problem; public ControlCouple(String src) { super(AptanaRDTPlugin.getDefault().getOptions(), src); } @Override protected String getOptionKey() { return AptanaRDTPlugin.COMPILER_PB_CONTROL_COUPLE; } @Override protected int getProblemID() { return IProblem.ControlCouple; } @Override public Object visitIfNode(IfNode visited) { Node elseBody = visited.getElseBody(); if (elseBody != null && !elseBody.equals(NilImplicitNode.NIL)) condition = visited.getCondition(); return super.visitIfNode(visited); } @Override public Object visitDefnNode(DefnNode visited) { args = ASTUtil.getArguments(visited.getArgsNode().getPre()); return super.visitDefnNode(visited); } @Override public void exitDefnNode(DefnNode visited) { args = null; if (problem) { // FIXME Create the problem on the arg node createProblem(visited.getPosition(), "Control Couple: Two code paths based on an argument to the method"); } problem = false; super.exitDefnNode(visited); } @Override public Object visitLocalVarNode(LocalVarNode visited) { if (args != null && visited.equals(condition)) { // check against method args String name = visited.getName(); if (args.contains(name)) { problem = true; } } return super.visitLocalVarNode(visited); } }