package com.aptana.rdt.internal.parser.warnings;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.jruby.ast.DefnNode;
import org.jruby.ast.DefsNode;
import org.jruby.ast.LocalAsgnNode;
import org.jruby.ast.RootNode;
import org.rubypeople.rdt.core.parser.warnings.RubyLintVisitor;
import com.aptana.rdt.AptanaRDTPlugin;
public class TooManyLocalsVisitor extends RubyLintVisitor {
public static final int DEFAULT_MAX_LOCALS = 4;
private int maxLocals;
private Set<String> locals;
public TooManyLocalsVisitor(String contents) {
this(AptanaRDTPlugin.getDefault().getOptions(), contents);
}
public TooManyLocalsVisitor(Map<String,String> options, String contents) {
super(options, contents);
maxLocals = getInt(AptanaRDTPlugin.COMPILER_PB_MAX_LOCALS, DEFAULT_MAX_LOCALS);
}
private int getInt(String key, int defaultValue) {
try {
return Integer.parseInt((String) fOptions.get(key));
} catch (NumberFormatException e) {
return defaultValue;
}
}
@Override
protected String getOptionKey() {
return AptanaRDTPlugin.COMPILER_PB_CODE_COMPLEXITY_LOCALS;
}
@Override
public Object visitRootNode(RootNode iVisited) {
locals = new HashSet<String>(); // FIXME Keep a scoped stack of locals?!
Object ins = super.visitRootNode(iVisited);
locals.clear();
return ins;
}
@Override
public Object visitDefsNode(DefsNode iVisited) {
locals = new HashSet<String>();
return super.visitDefsNode(iVisited);
}
@Override
public Object visitDefnNode(DefnNode iVisited) {
locals = new HashSet<String>();
return super.visitDefnNode(iVisited);
}
@Override
public Object visitLocalAsgnNode(LocalAsgnNode iVisited) {
locals.add(iVisited.getName());
return super.visitLocalAsgnNode(iVisited);
}
public void exitDefnNode(DefnNode iVisited) {
if (locals.size() > maxLocals) {
createProblem(iVisited.getNameNode().getPosition(), "Too many local variables: " + locals.size());
}
locals.clear();
}
@Override
public void exitDefsNode(DefsNode iVisited) {
if (locals.size() > maxLocals) {
createProblem(iVisited.getNameNode().getPosition(), "Too many local variables: " + locals.size());
}
locals.clear();
super.exitDefsNode(iVisited);
}
}