[Pydev-cvs] org.python.pydev/src/org/python/pydev/editor/dictionary PyDClassItem.java,1.1,1.2 PyDFun
Brought to you by:
fabioz
Update of /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/dictionary In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17511/src/org/python/pydev/editor/dictionary Modified Files: PyDClassItem.java PyDFunctionItem.java PopulateDictionary.java PyDictionary.java PyDLocalItem.java PyDEditorItem.java Log Message: Lots of improvement in detecting local variables Index: PyDFunctionItem.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/dictionary/PyDFunctionItem.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PyDFunctionItem.java 30 Mar 2004 01:03:37 -0000 1.1 --- PyDFunctionItem.java 31 Mar 2004 02:28:42 -0000 1.2 *************** *** 23,27 **** PopulateDictionary populator = new PopulateDictionary(this, subItems); try { ! node.traverse(populator); } catch (Exception e) { PydevPlugin.log(IStatus.ERROR, "Unexpected error populating ClassDef", e); --- 23,28 ---- PopulateDictionary populator = new PopulateDictionary(this, subItems); try { ! PopulateDictionary.FunctionDefTraverse(populator, node); ! //node.traverse(populator); } catch (Exception e) { PydevPlugin.log(IStatus.ERROR, "Unexpected error populating ClassDef", e); *************** *** 31,35 **** public String toString() { ! return "Function " + node.name + "\n" + subItems.toString(); } --- 32,38 ---- public String toString() { ! String dic = subItems.toString(); ! String dicString = dic.length() == 0 ? " []" : "\n[ "+dic+" ]\n"; ! return node.name + " FUNCTION DICTIONARY" + dicString; } Index: PopulateDictionary.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/dictionary/PopulateDictionary.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PopulateDictionary.java 30 Mar 2004 01:03:37 -0000 1.1 --- PopulateDictionary.java 31 Mar 2004 02:28:42 -0000 1.2 *************** *** 9,12 **** --- 9,57 ---- import org.python.parser.ast.*; + /** + * PopulateDictionary creates a hierarchy of dictionaries. + * + * Every dictionary includes: classes, methods, and local variables. + * Each class/method have their own dictionaries. + * + * The whole tree except for classes and nodes is traversed recursively by this visitor. + * Classes and function definitions create their own dictionaries and traverse + * their own portions of the tree. + * + * TODO + * Detecting locals inside the AST is problematic. There is no clear way to detect them, + * in Python locals need not be declared, so they appear automatically when used. This means + * that detecting locals will be a perpetual hack. I'll mark the local detection code inside + * this file "LOCALS" so that you can grep for it. + * + * My current strategy is to trap visits to Name token. All locals manifestations have to involve + * this token. But some Name's are not locals. The only way to trap this occurence is + * higher up in the visitor pattern: + * + * For example: + * TryExcept::exceptTypeHandler::node.type is a Name. + * To intercept this, I need to override: + * exceptHandlerType::traverse so that it does not visit node.type + * TryExcept::traverse to trap exceptHandlerType::traverse + * + * Current list of overrides: + * TryExcept: for exceptHandlerType::node + * FunctionDef + * Grepping through org.python.parser.TreeBuilder.java is useful. Here you can see how Name + * is created and used. + * TreeBuilder name usage: + * JJTDOT_OP: creates an Attribute with embedded name + * JJTFUNCDEF: Name is functon name + * JJTEXTRAARGLIST: Part of ExtraArg + * JJTEXTRAKEYWORDLIST: Part of ExtraArg + * JJTCLASSDEF: Part of ClassDef + * JJTGLOBAL: Part of Global + * JJTKEYWORD: Part of keywordType + * JJTIMPORTFROM: Part of ImportFrom + * JJTDOTTED_NAME: creates the whole dotted name with Name.Load opearator? + * JJTDOTTED_AS_NAME, JJTIMPORT_AS_NAME: aliasType... + * + */ + class PopulateDictionary extends VisitorBase { *************** *** 24,36 **** public void traverse(SimpleNode node) throws Exception { ! System.out.println("Traverse?"); } ! ! public Object visitAssign(Assign node) throws Exception { ! dict.addLocal(new PyDLocalItem(parent, node)); return null; } - public Object visitClassDef(ClassDef node) throws Exception { dict.addClass(new PyDClassItem(parent, node)); --- 69,80 ---- public void traverse(SimpleNode node) throws Exception { ! node.traverse(this); } ! ! public Object visitAttribute(Attribute node) throws Exception { ! System.out.println("visitAttribute " + node.attr); return null; } public Object visitClassDef(ClassDef node) throws Exception { dict.addClass(new PyDClassItem(parent, node)); *************** *** 42,44 **** --- 86,194 ---- return null; } + + /* Locals muck */ + + /* Every name we reach is a local */ + public Object visitName(Name node) throws Exception { + dict.addLocal(new PyDLocalItem(parent, node)); + node.traverse(this); + return null; + } + + /** + * Calls have function as a Name. + * do not traverse. + * Note: we might have to traverse Call's keywords and starargs + * Python example: + * printSomething() # printSomething is not a local + */ + public Object visitCall(Call node) throws Exception { + return null; + } + + /** + * ExceptHandler name declaration avoidance. + * To avoid: + try: + import readline + except ImportError: + * ImportError being declared in a dictionary, we need to not + * traverse TODO + */ + public Object visitTryExcept(TryExcept node) throws Exception { + tryExceptTraverse(node, this); + return null; + } + + /** + * ExceptHandler name declaration avoidance. + * Only difference is lines commented out + * @see visitTryExcept + */ + public void excepthandlerTypeTraverse(excepthandlerType node, VisitorIF visitor) throws Exception{ + // if (node.type != null) + // node.type.accept(visitor); + if (node.name != null) + node.name.accept(visitor); + if (node.body != null) { + for (int i = 0; i < node.body.length; i++) { + if (node.body[i] != null) + node.body[i].accept(visitor); + } + } + } + + /** + * Copy of TryExcept::traverse. + * The only difference is that I call excepthandlerTypeTraverse + * @see visitTryExcept + */ + public void tryExceptTraverse(TryExcept node, VisitorIF visitor) throws Exception { + if (node.body != null) { + for (int i = 0; i < node.body.length; i++) { + if (node.body[i] != null) + node.body[i].accept(visitor); + } + } + if (node.handlers != null) { + for (int i = 0; i < node.handlers.length; i++) { + if (node.handlers[i] != null) + excepthandlerTypeTraverse(node.handlers[i],this); // modified + } + } + if (node.orelse != null) { + for (int i = 0; i < node.orelse.length; i++) { + if (node.orelse[i] != null) + node.orelse[i].accept(visitor); + } + } + } + + static void argumentsTypeTraverse(PopulateDictionary visitor, argumentsType node) throws Exception { + if (node.args != null) { + for (int i = 0; i < node.args.length; i++) { + if (node.args[i] != null) + node.args[i].accept(visitor); + } + } + // if (defaults != null) { + // for (int i = 0; i < defaults.length; i++) { + // if (defaults[i] != null) + // defaults[i].accept(visitor); + // } + // } + + } + + static void FunctionDefTraverse(PopulateDictionary visitor, FunctionDef node) throws Exception { + if (node.args != null) + argumentsTypeTraverse(visitor, node.args); + // node.args.traverse(visitor); + if (node.body != null) { + for (int i = 0; i < node.body.length; i++) { + if (node.body[i] != null) + node.body[i].accept(visitor); + } + } + } } \ No newline at end of file Index: PyDLocalItem.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/dictionary/PyDLocalItem.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PyDLocalItem.java 30 Mar 2004 01:03:37 -0000 1.1 --- PyDLocalItem.java 31 Mar 2004 02:28:42 -0000 1.2 *************** *** 6,10 **** package org.python.pydev.editor.dictionary; ! import org.python.parser.ast.Assign; import org.eclipse.core.runtime.IStatus; import org.python.pydev.plugin.PydevPlugin; --- 6,10 ---- package org.python.pydev.editor.dictionary; ! import org.python.parser.ast.Name; import org.eclipse.core.runtime.IStatus; import org.python.pydev.plugin.PydevPlugin; *************** *** 16,22 **** public class PyDLocalItem extends PyDictionaryItem { ! Assign node; ! public PyDLocalItem(PyDictionaryItem parent, Assign node) { super(parent); this.node = node; --- 16,22 ---- public class PyDLocalItem extends PyDictionaryItem { ! Name node; ! public PyDLocalItem(PyDictionaryItem parent, Name node) { super(parent); this.node = node; *************** *** 31,38 **** public String toString() { ! String locals = ""; ! for (int i=0;i<node.targets.length; i++) ! locals += node.targets[i].toString(); ! return "Local " + locals + "\n" + subItems.toString(); } } --- 31,42 ---- public String toString() { ! return node.id; ! } ! ! /** ! * get the name of the local variable ! */ ! public String getName() { ! return node.id; } } Index: PyDEditorItem.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/dictionary/PyDEditorItem.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PyDEditorItem.java 30 Mar 2004 01:03:37 -0000 1.1 --- PyDEditorItem.java 31 Mar 2004 02:28:42 -0000 1.2 *************** *** 56,60 **** public String toString() { ! return "Top node\n" + subItems.toString(); } } --- 56,60 ---- public String toString() { ! return "##### TOP NODE #########\n" + subItems.toString(); } } Index: PyDictionary.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/dictionary/PyDictionary.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PyDictionary.java 30 Mar 2004 01:03:37 -0000 1.1 --- PyDictionary.java 31 Mar 2004 02:28:42 -0000 1.2 *************** *** 36,42 **** public void addLocal(PyDLocalItem newLocal) { ! locals.add(newLocal); } /** * For debugging, pretty print the dictionary --- 36,50 ---- public void addLocal(PyDLocalItem newLocal) { ! // eliminate dupes ! if (!hasLocal(newLocal)) ! locals.add(newLocal); } + boolean hasLocal(PyDLocalItem local) { + for (Iterator i = locals.iterator();i.hasNext();) + if (local.getName().equals(((PyDLocalItem)i.next()).getName())) + return true; + return false; + } /** * For debugging, pretty print the dictionary *************** *** 49,53 **** while (i.hasNext()) buf.append(i.next().toString()); ! buf.append("\n"); } if (!functions.isEmpty()) { --- 57,61 ---- while (i.hasNext()) buf.append(i.next().toString()); ! // buf.append("\n"); } if (!functions.isEmpty()) { *************** *** 56,67 **** while (i.hasNext()) buf.append(i.next().toString()); ! buf.append("\n"); } if (!locals.isEmpty()) { buf.append("Locals: "); Iterator i = locals.iterator(); ! while (i.hasNext()) buf.append(i.next().toString()); ! buf.append("\n"); } return buf.toString(); --- 64,77 ---- while (i.hasNext()) buf.append(i.next().toString()); ! // buf.append("\n"); } if (!locals.isEmpty()) { buf.append("Locals: "); Iterator i = locals.iterator(); ! while (i.hasNext()) { buf.append(i.next().toString()); ! buf.append(","); ! } ! // buf.append("\n"); } return buf.toString(); Index: PyDClassItem.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/dictionary/PyDClassItem.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PyDClassItem.java 30 Mar 2004 01:03:37 -0000 1.1 --- PyDClassItem.java 31 Mar 2004 02:28:42 -0000 1.2 *************** *** 31,35 **** public String toString() { ! return "Class " + node.name + "\n" + subItems.toString(); } } --- 31,35 ---- public String toString() { ! return node.name + " CLASS & ITS DICTIONARY\n" + "[" + subItems.toString() + "]"; } } |