/** * Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ /* * Created on 12/06/2005 */ package org.python.pydev.parser.visitors.scope; import org.python.pydev.parser.jython.SimpleNode; import org.python.pydev.parser.jython.ast.Assign; import org.python.pydev.parser.jython.ast.Attribute; import org.python.pydev.parser.jython.ast.ClassDef; import org.python.pydev.parser.jython.ast.Name; import org.python.pydev.parser.jython.ast.Tuple; import org.python.pydev.parser.jython.ast.exprType; import org.python.pydev.parser.jython.ast.stmtType; /** * This class is used so that after traversing the AST, we have a simple structure for navigating * upon its nodes; * * This structure should provide: * - Imports * - Classes (and attributes) * - Methods * * * * Note: it does not only provide global information, but also inner information, such as methods from a class. * * @author Fabio */ public class DefinitionsASTIteratorVisitor extends EasyASTIteratorVisitor { @Override public Object visitAssign(Assign node) throws Exception { return visitAssign(this, node); } public static Object visitAssign(EasyAstIteratorBase visitor, Assign node) throws Exception { return visitAssign(visitor, node, true); } /** * @see org.python.pydev.parser.jython.ast.VisitorBase#visitAssign(org.python.pydev.parser.jython.ast.Assign) */ public static Object visitAssign(EasyAstIteratorBase visitor, Assign node, boolean visitUnhandledAndTraverse) throws Exception { visitTargetsInAssign(visitor, node.targets); if (visitUnhandledAndTraverse) { Object ret = visitor.unhandled_node(node); visitor.traverse(node); return ret; } else { return null; } } /** * Given a visitor and the targets found in an assign, visit them to find class attributes / instance variables. * * @param visitor the visitor * @param targets the expressions in the target */ private static void visitTargetsInAssign(EasyAstIteratorBase visitor, exprType[] targets) { if (targets == null) { return; } for (int i = 0; i < targets.length; i++) { exprType t = targets[i]; if (t instanceof Tuple) { Tuple tuple = (Tuple) t; visitTargetsInAssign(visitor, tuple.elts); } visitTargetInAssign(visitor, t); } } /** * Visit a single target found in an assign to create a class attributes / instance variables if possible. * @param visitor the visitor * @param t the expression to visit */ private static void visitTargetInAssign(EasyAstIteratorBase visitor, exprType t) { if (t instanceof Name) { //we are in the class declaration if (visitor.isInClassDecl() || visitor.isInGlobal()) { //add the attribute for the class visitor.atomic(t); } } else if (t instanceof Attribute) { //we are in a method from the class if (visitor.isInClassMethodDecl()) { Attribute a = (Attribute) t; if (a.value instanceof Name) { //it is an instance variable attribute Name n = (Name) a.value; if (n.id.equals("self")) { visitor.atomic(t); } } } else if (visitor.isInClassDecl() || visitor.isInGlobal()) { //add the attribute for the class visitor.atomic(t); } } } /** * Creates the iterator and traverses the passed root so that the results can be gotten. */ public static DefinitionsASTIteratorVisitor create(SimpleNode root) { if (root == null) { return null; } DefinitionsASTIteratorVisitor visitor = new DefinitionsASTIteratorVisitor(); try { root.accept(visitor); } catch (Exception e) { throw new RuntimeException(e); } return visitor; } /** * Creates the iterator and traverses the passed root so that the results can be gotten. */ public static DefinitionsASTIteratorVisitor createForChildren(ClassDef root) { if (root == null) { return null; } DefinitionsASTIteratorVisitor visitor = new DefinitionsASTIteratorVisitor(); try { stmtType[] body = root.body; if (body != null) { for (int i = 0; i < body.length; i++) { if (body[i] != null) { body[i].accept(visitor); } } } } catch (Exception e) { throw new RuntimeException(e); } return visitor; } }