package org.rubypeople.rdt.internal.core.util; import java.util.Iterator; import org.jruby.ast.AliasNode; import org.jruby.ast.AndNode; import org.jruby.ast.ArgsCatNode; import org.jruby.ast.ArgsNode; import org.jruby.ast.ArgsPushNode; import org.jruby.ast.ArrayNode; import org.jruby.ast.AttrAssignNode; import org.jruby.ast.BackRefNode; import org.jruby.ast.BeginNode; import org.jruby.ast.BignumNode; import org.jruby.ast.BlockArgNode; import org.jruby.ast.BlockNode; import org.jruby.ast.BlockPassNode; import org.jruby.ast.BreakNode; import org.jruby.ast.CallNode; import org.jruby.ast.CaseNode; import org.jruby.ast.ClassNode; import org.jruby.ast.ClassVarAsgnNode; import org.jruby.ast.ClassVarDeclNode; import org.jruby.ast.ClassVarNode; import org.jruby.ast.Colon2Node; import org.jruby.ast.Colon3Node; import org.jruby.ast.ConstDeclNode; import org.jruby.ast.ConstNode; import org.jruby.ast.DAsgnNode; import org.jruby.ast.DRegexpNode; import org.jruby.ast.DStrNode; import org.jruby.ast.DSymbolNode; import org.jruby.ast.DVarNode; import org.jruby.ast.DXStrNode; import org.jruby.ast.DefinedNode; import org.jruby.ast.DefnNode; import org.jruby.ast.DefsNode; import org.jruby.ast.DotNode; import org.jruby.ast.EnsureNode; import org.jruby.ast.EvStrNode; import org.jruby.ast.FCallNode; import org.jruby.ast.FalseNode; import org.jruby.ast.FixnumNode; import org.jruby.ast.FlipNode; import org.jruby.ast.FloatNode; import org.jruby.ast.ForNode; import org.jruby.ast.GlobalAsgnNode; import org.jruby.ast.GlobalVarNode; import org.jruby.ast.HashNode; import org.jruby.ast.IfNode; import org.jruby.ast.InstAsgnNode; import org.jruby.ast.InstVarNode; import org.jruby.ast.IterNode; import org.jruby.ast.LocalAsgnNode; import org.jruby.ast.LocalVarNode; import org.jruby.ast.Match2Node; import org.jruby.ast.Match3Node; import org.jruby.ast.MatchNode; import org.jruby.ast.ModuleNode; import org.jruby.ast.MultipleAsgn19Node; import org.jruby.ast.MultipleAsgnNode; import org.jruby.ast.NewlineNode; import org.jruby.ast.NextNode; import org.jruby.ast.NilNode; import org.jruby.ast.Node; import org.jruby.ast.NotNode; import org.jruby.ast.NthRefNode; import org.jruby.ast.OpAsgnAndNode; import org.jruby.ast.OpAsgnNode; import org.jruby.ast.OpAsgnOrNode; import org.jruby.ast.OpElementAsgnNode; import org.jruby.ast.OrNode; import org.jruby.ast.PostExeNode; import org.jruby.ast.PreExeNode; import org.jruby.ast.RedoNode; import org.jruby.ast.RegexpNode; import org.jruby.ast.RescueBodyNode; import org.jruby.ast.RescueNode; import org.jruby.ast.RestArgNode; import org.jruby.ast.RetryNode; import org.jruby.ast.ReturnNode; import org.jruby.ast.RootNode; import org.jruby.ast.SClassNode; import org.jruby.ast.SValueNode; import org.jruby.ast.SelfNode; import org.jruby.ast.SplatNode; import org.jruby.ast.StrNode; import org.jruby.ast.SuperNode; import org.jruby.ast.SymbolNode; import org.jruby.ast.ToAryNode; import org.jruby.ast.TrueNode; import org.jruby.ast.UndefNode; import org.jruby.ast.UntilNode; import org.jruby.ast.VAliasNode; import org.jruby.ast.VCallNode; import org.jruby.ast.WhenNode; import org.jruby.ast.WhileNode; import org.jruby.ast.XStrNode; import org.jruby.ast.YieldNode; import org.jruby.ast.ZArrayNode; import org.jruby.ast.ZSuperNode; import org.jruby.ast.visitor.NodeVisitor; import org.jruby.lexer.yacc.ISourcePosition; import org.rubypeople.rdt.core.IMember; import org.rubypeople.rdt.core.ISourceRange; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.internal.core.SourceRefElement; public class DOMFinder implements NodeVisitor { // XXX Refactor out all sorts of common code between this and RubyScriptStructureBuilder // XXX Think about abstracting to higher level AST (and visitor) that just deals with class/method/module/etc declarations like the JDT public Node foundNode = null; private Node ast; private SourceRefElement element; private int rangeStart = -1, rangeLength = 0; public DOMFinder(Node ast, SourceRefElement element) { this.ast = ast; this.element = element; } public Object visitAliasNode(AliasNode arg0) { return null; } public Object visitAndNode(AndNode iVisited) { visitNode(iVisited.getFirstNode()); visitNode(iVisited.getSecondNode()); return null; } public Object visitArgsCatNode(ArgsCatNode iVisited) { visitNode(iVisited.getFirstNode()); visitNode(iVisited.getSecondNode()); return null; } public Object visitArgsNode(ArgsNode iVisited) { visitNode(iVisited.getBlock()); if (iVisited.getOptArgs() != null) { visitIter(iVisited.getOptArgs().childNodes().iterator()); } return null; } private Object visitIter(Iterator<Node> iterator) { while (iterator.hasNext()) { visitNode(iterator.next()); } return null; } public Object visitArrayNode(ArrayNode iVisited) { visitIter(iVisited.childNodes().iterator()); return null; } public Object visitBackRefNode(BackRefNode arg0) { return null; } public Object visitBeginNode(BeginNode iVisited) { visitNode(iVisited.getBodyNode()); return null; } public Object visitBignumNode(BignumNode arg0) { return null; } public Object visitBlockArgNode(BlockArgNode arg0) { return null; } public Object visitBlockNode(BlockNode iVisited) { visitIter(iVisited.childNodes().iterator()); return null; } public Object visitBlockPassNode(BlockPassNode iVisited) { visitNode(iVisited.getArgsNode()); visitNode(iVisited.getBodyNode()); return null; } public Object visitBreakNode(BreakNode iVisited) { visitNode(iVisited.getValueNode()); return null; } public Object visitCallNode(CallNode iVisited) { visitNode(iVisited.getReceiverNode()); visitNode(iVisited.getArgsNode()); visitNode(iVisited.getIterNode()); return null; } public Object visitCaseNode(CaseNode iVisited) { visitNode(iVisited.getCaseNode()); visitNode(iVisited.getCases()); return null; } public Object visitClassNode(ClassNode node) { String name = getFullyQualifiedName(node.getCPath()); ISourcePosition pos = node.getPosition(); int nameStart = pos.getStartOffset() + "class".length() + 1; if (!found(node, nameStart, name.length())) { visitNode(node.getSuperNode()); visitNode(node.getBodyNode()); } return null; } private Object visitNode(Node iVisited) { if (iVisited != null) iVisited.accept(this); return null; } private boolean found(Node node, int start, int length) { if (start == this.rangeStart && length == this.rangeLength) { this.foundNode = node; } return false; } private String getFullyQualifiedName(Node node) { if (node == null) return ""; if (node instanceof ConstNode) { ConstNode constNode = (ConstNode) node; return constNode.getName(); } if (node instanceof Colon2Node) { Colon2Node colonNode = (Colon2Node) node; String prefix = getFullyQualifiedName(colonNode.getLeftNode()); if (prefix.length() > 0) prefix = prefix + "::"; return prefix + colonNode.getName(); } return ""; } public Object visitClassVarAsgnNode(ClassVarAsgnNode arg0) { return null; } public Object visitClassVarDeclNode(ClassVarDeclNode arg0) { return null; } public Object visitClassVarNode(ClassVarNode arg0) { return null; } public Object visitColon2Node(Colon2Node arg0) { return null; } public Object visitColon3Node(Colon3Node arg0) { return null; } public Object visitConstDeclNode(ConstDeclNode arg0) { return null; } public Object visitConstNode(ConstNode arg0) { return null; } public Object visitDAsgnNode(DAsgnNode arg0) { return null; } public Object visitDRegxNode(DRegexpNode arg0) { return null; } public Object visitDStrNode(DStrNode arg0) { return null; } public Object visitDSymbolNode(DSymbolNode arg0) { return null; } public Object visitDVarNode(DVarNode arg0) { return null; } public Object visitDXStrNode(DXStrNode arg0) { return null; } public Object visitDefinedNode(DefinedNode arg0) { return null; } public Object visitDefnNode(DefnNode iVisited) { String name = iVisited.getName(); ISourcePosition pos = iVisited.getPosition(); int nameStart = pos.getStartOffset() + "def".length() + 1; if (!found(iVisited, nameStart, name.length()) ) { visitNode(iVisited.getArgsNode()); visitNode(iVisited.getBodyNode()); } return null; } public Object visitDefsNode(DefsNode iVisited) { String name; String receiver = ASTUtil.stringRepresentation(iVisited.getReceiverNode()); if (receiver != null && receiver.trim().length() > 0) { name = receiver + "." + iVisited.getName(); } else { name = iVisited.getName(); } ISourcePosition pos = iVisited.getPosition(); int nameStart = pos.getStartOffset() + "def".length() + 1; if (!found(iVisited, nameStart, name.length())) { visitNode(iVisited.getReceiverNode()); visitNode(iVisited.getArgsNode()); visitNode(iVisited.getBodyNode()); } return null; } public Object visitDotNode(DotNode arg0) { return null; } public Object visitEnsureNode(EnsureNode arg0) { return null; } public Object visitEvStrNode(EvStrNode arg0) { return null; } public Object visitFCallNode(FCallNode arg0) { return null; } public Object visitFalseNode(FalseNode arg0) { return null; } public Object visitFixnumNode(FixnumNode arg0) { return null; } public Object visitFlipNode(FlipNode arg0) { return null; } public Object visitFloatNode(FloatNode arg0) { return null; } public Object visitForNode(ForNode arg0) { return null; } public Object visitGlobalAsgnNode(GlobalAsgnNode arg0) { return null; } public Object visitGlobalVarNode(GlobalVarNode arg0) { return null; } public Object visitHashNode(HashNode arg0) { return null; } public Object visitIfNode(IfNode arg0) { return null; } public Object visitInstAsgnNode(InstAsgnNode arg0) { return null; } public Object visitInstVarNode(InstVarNode arg0) { return null; } public Object visitIterNode(IterNode arg0) { return null; } public Object visitLocalAsgnNode(LocalAsgnNode arg0) { return null; } public Object visitLocalVarNode(LocalVarNode arg0) { return null; } public Object visitMatch2Node(Match2Node arg0) { return null; } public Object visitMatch3Node(Match3Node arg0) { return null; } public Object visitMatchNode(MatchNode arg0) { return null; } public Object visitModuleNode(ModuleNode arg0) { return null; } public Object visitMultipleAsgnNode(MultipleAsgnNode arg0) { return null; } public Object visitNewlineNode(NewlineNode iVisited) { visitNode(iVisited.getNextNode()); return null; } public Object visitNextNode(NextNode iVisited) { visitNode(iVisited.getValueNode()); return null; } public Object visitNilNode(NilNode arg0) { return null; } public Object visitNotNode(NotNode arg0) { return null; } public Object visitNthRefNode(NthRefNode arg0) { return null; } public Object visitOpAsgnAndNode(OpAsgnAndNode arg0) { return null; } public Object visitOpAsgnNode(OpAsgnNode arg0) { return null; } public Object visitOpAsgnOrNode(OpAsgnOrNode arg0) { return null; } public Object visitOpElementAsgnNode(OpElementAsgnNode arg0) { return null; } public Object visitOrNode(OrNode arg0) { return null; } public Object visitPreExeNode(PreExeNode iVisited) { return null; } public Object visitPostExeNode(PostExeNode arg0) { return null; } public Object visitRedoNode(RedoNode arg0) { return null; } public Object visitRegexpNode(RegexpNode arg0) { return null; } public Object visitRescueBodyNode(RescueBodyNode arg0) { return null; } public Object visitRescueNode(RescueNode arg0) { return null; } public Object visitRetryNode(RetryNode arg0) { return null; } public Object visitReturnNode(ReturnNode arg0) { return null; } public Object visitSClassNode(SClassNode arg0) { return null; } public Object visitSValueNode(SValueNode arg0) { return null; } public Object visitSelfNode(SelfNode arg0) { return null; } public Object visitSplatNode(SplatNode arg0) { return null; } public Object visitStrNode(StrNode arg0) { return null; } public Object visitSuperNode(SuperNode arg0) { return null; } public Object visitSymbolNode(SymbolNode arg0) { return null; } public Object visitToAryNode(ToAryNode arg0) { return null; } public Object visitTrueNode(TrueNode arg0) { return null; } public Object visitUndefNode(UndefNode arg0) { return null; } public Object visitUntilNode(UntilNode arg0) { return null; } public Object visitVAliasNode(VAliasNode arg0) { return null; } public Object visitVCallNode(VCallNode arg0) { return null; } public Object visitWhenNode(WhenNode arg0) { return null; } public Object visitWhileNode(WhileNode arg0) { return null; } public Object visitXStrNode(XStrNode arg0) { return null; } public Object visitYieldNode(YieldNode arg0) { return null; } public Object visitZArrayNode(ZArrayNode arg0) { return null; } public Object visitZSuperNode(ZSuperNode node) { return null; } public Node search() throws RubyModelException { ISourceRange range = null; if (this.element instanceof IMember) range = ((IMember) this.element).getNameRange(); else range = this.element.getSourceRange(); this.rangeStart = range.getOffset(); this.rangeLength = range.getLength(); this.ast.accept(this); return this.foundNode; } public Object visitArgsPushNode(ArgsPushNode node) { return null; } public Object visitAttrAssignNode(AttrAssignNode iVisited) { return null; } public Object visitRootNode(RootNode iVisited) { visitNode(iVisited.getBodyNode()); return null; } public Object visitRestArgNode(RestArgNode visited) { return null; } public Object visitMultipleAsgnNode(MultipleAsgn19Node visited) { return null; } }