package org.rubypeople.rdt.core.parser.warnings; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.jruby.ast.ArgsNode; import org.jruby.ast.BlockNode; import org.jruby.ast.ClassNode; import org.jruby.ast.DefnNode; import org.jruby.ast.DefsNode; import org.jruby.ast.HashNode; import org.jruby.ast.IfNode; import org.jruby.ast.ModuleNode; import org.jruby.ast.Node; import org.jruby.ast.RescueBodyNode; import org.jruby.ast.RootNode; import org.jruby.ast.SClassNode; import org.jruby.ast.WhenNode; import org.jruby.lexer.yacc.ISourcePosition; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.compiler.CategorizedProblem; import org.rubypeople.rdt.core.compiler.IProblem; import org.rubypeople.rdt.internal.core.parser.Error; import org.rubypeople.rdt.internal.core.parser.InOrderVisitor; import org.rubypeople.rdt.internal.core.parser.Warning; import org.rubypeople.rdt.internal.core.util.ASTUtil; public abstract class RubyLintVisitor extends InOrderVisitor { private String contents; protected Map<String, String> fOptions; private List<CategorizedProblem> problems; public RubyLintVisitor(String contents) { this(RubyCore.getOptions(), contents); } public RubyLintVisitor(Map<String, String> options, String contents) { this.problems = new ArrayList<CategorizedProblem>(); this.contents = contents; this.fOptions = options; } protected String getSource(Node node) { return ASTUtil.getSource(contents, node); } protected String getSource(int start, int end) { if (start > end) { int temp = end; end = start; start = temp; } if (contents.length() < end) end = contents.length(); if (start < 0) start = 0; return new String(contents.substring(start, end)); } public List<CategorizedProblem> getProblems() { return problems; } public boolean isIgnored() { String value = getSeverity(); if (value != null && value.equals(RubyCore.IGNORE)) return true; return false; } protected void createProblem(ISourcePosition position, String message) { String value = getSeverity(); if (value != null && value.equals(RubyCore.IGNORE)) return; CategorizedProblem problem; if (value != null && value.equals(RubyCore.ERROR)) problem = new Error(position, message, getProblemID()); else problem = new Warning(position, message, getProblemID()); problems.add(problem); } protected String getSeverity() { return (String) fOptions.get(getOptionKey()); } @Override protected Object visitNode(Node iVisited) { return null; } /** * The key used to store the error/warning severity option. * * @return a String key */ abstract protected String getOptionKey(); /** * Meant to be overridden by classes needing to perform some action when a class definition was exited. * * @param iVisited */ public void exitClassNode(ClassNode iVisited) { } /** * To be overridden by subclasses who need to run particular behavior/code when exiting a method definition. * * @param iVisited */ public void exitDefnNode(DefnNode iVisited) { } /** * To be overridden by subclasses who need to run particular behavior/code when exiting a singleton method * definition. * * @param iVisited */ public void exitIfNode(IfNode iVisited) { } /** * To be overriden by subclasses who need to run particular behavior/code when exiting a singleton method * definition. * * @param iVisited */ public void exitBlockNode(BlockNode iVisited) { } /** * To be overridden by subclasses who need to run particular behavior/code when exiting a singleton method * definition. * * @param iVisited */ public void exitDefsNode(DefsNode iVisited) { } /** * To be overridden by subclasses who need to run particular behavior/code when exiting a singleton method * definition. * * @param iVisited */ public void exitModuleNode(ModuleNode iVisited) { } /** * To be overridden by subclasses who need to run particular behavior/code when exiting a singleton method * definition. * * @param iVisited */ public void exitWhenNode(WhenNode iVisited) { } /** * To be overridden by subclasses who need to run particular behavior/code when exiting a singleton method * definition. * * @param iVisited */ public void exitSClassNode(SClassNode iVisited) { } /** * To be overridden by subclasses who need to run particular behavior/code when exiting a method signature. * * @param iVisited */ public void exitArgsNode(ArgsNode iVisited) { } /** * To be overridden by subclasses who need to run particular behavior/code when exiting rescue body. * * @param iVisited */ public void exitRescueBodyNode(RescueBodyNode iVisited) { } /** * To be overridden by subclasses who need to run particular behavior/code when exiting a hash node. * * @param iVisited */ public void exitHashNode(HashNode iVisited) { } /** * To be overridden by subclasses who need to run particular behavior/code when exiting the AST. * * @param iVisited */ public void exitRootNode(RootNode iVisited) { } protected int getProblemID() { return IProblem.Uncategorized; } @Override public Object visitArgsNode(ArgsNode iVisited) { Object ins = super.visitArgsNode(iVisited); exitArgsNode(iVisited); return ins; } @Override public Object visitBlockNode(BlockNode iVisited) { Object ins = super.visitBlockNode(iVisited); exitBlockNode(iVisited); return ins; } @Override public Object visitClassNode(ClassNode iVisited) { Object ins = super.visitClassNode(iVisited); exitClassNode(iVisited); return ins; } @Override public Object visitDefnNode(DefnNode iVisited) { Object ins = super.visitDefnNode(iVisited); exitDefnNode(iVisited); return ins; } @Override public Object visitDefsNode(DefsNode iVisited) { Object ins = super.visitDefsNode(iVisited); exitDefsNode(iVisited); return ins; } @Override public Object visitHashNode(HashNode iVisited) { Object ins = super.visitHashNode(iVisited); exitHashNode(iVisited); return ins; } @Override public Object visitIfNode(IfNode iVisited) { Object ins = super.visitIfNode(iVisited); exitIfNode(iVisited); return ins; } @Override public Object visitModuleNode(ModuleNode iVisited) { Object ins = super.visitModuleNode(iVisited); exitModuleNode(iVisited); return ins; } @Override public Object visitRescueBodyNode(RescueBodyNode iVisited) { Object ins = super.visitRescueBodyNode(iVisited); exitRescueBodyNode(iVisited); return ins; } @Override public Object visitRootNode(RootNode iVisited) { problems.clear(); Object ret = super.visitRootNode(iVisited); exitRootNode(iVisited); return ret; } @Override public Object visitSClassNode(SClassNode iVisited) { Object ins = super.visitSClassNode(iVisited); exitSClassNode(iVisited); return ins; } @Override public Object visitWhenNode(WhenNode iVisited) { Object ins = super.visitWhenNode(iVisited); exitWhenNode(iVisited); return ins; } }