[Pydev-cvs] org.python.pydev/src/org/python/pydev/outline ParsedModel.java,1.3,1.4 ParsedItem.java,1
Brought to you by:
fabioz
From: Aleksandar T. <at...@us...> - 2004-04-10 02:01:39
|
Update of /cvsroot/pydev/org.python.pydev/src/org/python/pydev/outline In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv649/src/org/python/pydev/outline Modified Files: ParsedModel.java ParsedItem.java ParsedLabelProvider.java PyOutlinePage.java IOutlineModel.java RawPartitionModel.java Removed Files: SelectionPosition.java Log Message: Huge code rewrite. I've implemented a Python model. Model is based in AST tree, but should be simpler to use. No more visitor pattern. OutlineView and Navigation actions have been reworked to use new model, instead of traversing AST. Added Hyperlinking capability, but goto is not implemetned yet. Index: PyOutlinePage.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/outline/PyOutlinePage.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** PyOutlinePage.java 5 Mar 2004 22:07:04 -0000 1.6 --- PyOutlinePage.java 10 Apr 2004 01:48:12 -0000 1.7 *************** *** 25,28 **** --- 25,29 ---- import org.eclipse.ui.views.contentoutline.ContentOutlinePage; import org.python.pydev.editor.PyEdit; + import org.python.pydev.editor.model.AbstractNode; import org.python.pydev.ui.ImageCache; import org.python.pydev.ui.UIConstants; *************** *** 109,113 **** */ public ParsedModel getParsedModel() { ! return new ParsedModel(this, editorView.getParser()); } --- 110,114 ---- */ public ParsedModel getParsedModel() { ! return new ParsedModel(this, editorView); } *************** *** 205,212 **** public void selectionChanged(SelectionChangedEvent event) { StructuredSelection sel = (StructuredSelection)tree.getSelection(); ! SelectionPosition newSel = model.getSelectionPosition(sel); ! if (newSel == null) ! return; ! editorView.setSelection(newSel); } }; --- 206,211 ---- public void selectionChanged(SelectionChangedEvent event) { StructuredSelection sel = (StructuredSelection)tree.getSelection(); ! AbstractNode node = model.getSelectionPosition(sel); ! editorView.revealModelNode(node); } }; --- SelectionPosition.java DELETED --- Index: ParsedItem.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/outline/ParsedItem.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** ParsedItem.java 5 Mar 2004 22:04:44 -0000 1.6 --- ParsedItem.java 10 Apr 2004 01:48:12 -0000 1.7 *************** *** 7,104 **** import java.util.ArrayList; - import org.python.parser.SimpleNode; - import org.python.parser.ast.ClassDef; - import org.python.parser.ast.Compare; - import org.python.parser.ast.FunctionDef; - import org.python.parser.ast.If; - import org.python.parser.ast.Import; import org.python.parser.ast.ImportFrom; - import org.python.parser.ast.Name; - import org.python.parser.ast.Str; - import org.python.parser.ast.VisitorBase; import org.python.parser.ast.aliasType; /** * ParsedModel is composed of ParsedItems. * ! * <p>The model gets an AST (Abstract Syntax Tree) from jython's parser ! * and this is then converted to a tree of ParsedItems */ public class ParsedItem { ParsedItem parent; ParsedItem[] children = null; // array of modTypes ! SimpleNode token; // parser token that this node represents ! ! /** ! * Traverses the parsed tree. ! * ! * <p>Fills the array list with the items we are interested in. ! */ ! static class Visitor extends VisitorBase { ! ! ArrayList fill; ! ParsedItem parent; ! ! boolean hasImports; ! ParsedItem imports; ! ! public Visitor(ParsedItem parent, ArrayList fill) { ! this.parent = parent; ! this.fill = fill; ! } ! ! protected Object unhandled_node(SimpleNode node) throws Exception { ! return null; ! } ! ! public void traverse(SimpleNode node) throws Exception {} ! ! public Object visitClassDef(ClassDef node) throws Exception { ! fill.add(new ParsedItem(parent, node)); ! return null; ! } ! ! public Object visitImport(Import node) throws Exception { ! fill.add(new ParsedItem(parent, node)); ! return null; ! } ! ! public Object visitImportFrom(ImportFrom node) throws Exception { ! fill.add(new ParsedItem(parent, node)); ! return null; ! } ! ! public Object visitFunctionDef(FunctionDef node) throws Exception { ! fill.add(new ParsedItem(parent, node)); ! return null; ! } ! ! // On if statements, we are looking to tag if __name__ == 'main' idiom ! public Object visitIf(If node) throws Exception { ! if (node.test instanceof Compare) { ! Compare compareNode = (Compare)node.test; ! // handcrafted structure walking ! if (compareNode.left instanceof Name ! && ((Name)compareNode.left).id.equals("__name__") ! && compareNode.ops != null ! && compareNode.ops.length == 1 ! && compareNode.ops[0] == Compare.Eq) ! if ( true ! && compareNode.comparators != null ! && compareNode.comparators.length == 1 ! && compareNode.comparators[0] instanceof Str ! && ((Str)compareNode.comparators[0]).s.equals("__main__")) ! fill.add(new ParsedItem(parent, node)); ! } ! return super.visitIf(node); ! } ! } ! public ParsedItem(ParsedItem parent, SimpleNode token) { this.parent = parent; this.token = token; } ! public SimpleNode getToken() { return token; } --- 7,32 ---- import java.util.ArrayList; + import java.util.Iterator; import org.python.parser.ast.ImportFrom; import org.python.parser.ast.aliasType; + import org.python.pydev.editor.model.*; /** * ParsedModel is composed of ParsedItems. * ! * <p>The model traverses Python model to get a tree of items for display. ! * We have to deal with token */ public class ParsedItem { ParsedItem parent; ParsedItem[] children = null; // array of modTypes ! AbstractNode token; // parser token that this node represents. Can be null! ! public ParsedItem(ParsedItem parent, AbstractNode token) { this.parent = parent; this.token = token; } ! public AbstractNode getToken() { return token; } *************** *** 108,143 **** } ! /* ! * @return where in the document is this item located ! */ ! public SelectionPosition getPosition() { ! return getPosition(token); ! } ! ! /* ! * @return where in the document is this item located */ ! public static SelectionPosition getPosition(SimpleNode token) { ! int startOffset = 0; ! boolean wholeLine = false; ! if (token instanceof ClassDef) { ! startOffset = 5; ! } ! else if (token instanceof FunctionDef) { ! startOffset = 3; ! } ! else if (token instanceof Import) { ! startOffset = -1; ! } ! else { ! // for others, just select the whole line, since the syntax tree -> document position calculation can be painful ! wholeLine = true; } - - SelectionPosition position = new SelectionPosition(token.beginLine, token.beginColumn+startOffset, toString(token).length()); - - if (wholeLine) - position.column = SelectionPosition.WHOLE_LINE; - return position; } --- 36,59 ---- } ! /** ! * Traverses AST model, and puts its children into our tree */ ! private void adoptChildrenOfNode(AbstractNode node, ArrayList children) { ! if (node == null) ! return; ! Iterator i = node.getChildren().iterator(); ! while (i.hasNext()) { ! AbstractNode child = (AbstractNode)i.next(); ! // these are the nodes we display ! if (child instanceof ClassNode || ! child instanceof FunctionNode || ! child instanceof ImportNode || ! child instanceof ImportFromNode || ! child instanceof NameEqualsMainNode) ! children.add(new ParsedItem(this, child)); ! if (! (child instanceof ClassNode) && !(child instanceof FunctionNode)) ! // functions & class will have their own children, do not traverse now ! adoptChildrenOfNode(child, children); } } *************** *** 145,158 **** if (children == null) { ArrayList allMyChildren = new ArrayList(); ! Visitor v = new Visitor(this, allMyChildren); ! try { ! if (token != null) ! token.traverse(v); // traversal fills in the children ! children = new ParsedItem[allMyChildren.size()]; ! for (int i=0; i<allMyChildren.size();i++) ! children[i] = (ParsedItem)allMyChildren.get(i); ! } catch (Exception e) { ! e.printStackTrace(); ! } } return children; --- 61,68 ---- if (children == null) { ArrayList allMyChildren = new ArrayList(); ! adoptChildrenOfNode(token, allMyChildren); ! children = new ParsedItem[allMyChildren.size()]; ! for (int i=0; i<allMyChildren.size();i++) ! children[i] = (ParsedItem)allMyChildren.get(i); } return children; *************** *** 164,176 **** } ! public static String toString(SimpleNode token) { ! if (token instanceof ClassDef) { ! return ((ClassDef)token).name; } ! else if (token instanceof FunctionDef) { ! return ((FunctionDef)token).name; } ! else if (token instanceof Import) { ! aliasType[] imports = ((Import)token).names; StringBuffer retVal = new StringBuffer(); for (int i=0; i<imports.length; i++) { --- 74,88 ---- } ! public static String toString(AbstractNode token) { ! if (token == null) ! return "null"; ! if (token instanceof ClassNode) { ! return ((ClassNode)token).astNode.name; } ! else if (token instanceof FunctionNode) { ! return ((FunctionNode)token).astNode.name; } ! else if (token instanceof ImportNode) { ! aliasType[] imports = ((ImportNode)token).astNode.names; StringBuffer retVal = new StringBuffer(); for (int i=0; i<imports.length; i++) { *************** *** 181,187 **** return retVal.toString(); } ! else if (token instanceof ImportFrom) { // from wxPython.wx import * ! ImportFrom importToken = (ImportFrom)token; StringBuffer modules = new StringBuffer(); for (int i=0; i<importToken.names.length;i++) { --- 93,99 ---- return retVal.toString(); } ! else if (token instanceof ImportFromNode) { // from wxPython.wx import * ! ImportFrom importToken = ((ImportFromNode)token).astNode; StringBuffer modules = new StringBuffer(); for (int i=0; i<importToken.names.length;i++) { *************** *** 195,199 **** return importToken.module + ".(" + modules.toString() + ")"; } ! else if (token instanceof If) { return "__name__ == main"; } --- 107,111 ---- return importToken.module + ".(" + modules.toString() + ")"; } ! else if (token instanceof NameEqualsMainNode) { return "__name__ == main"; } *************** *** 209,221 **** public int getClassRanking() { int rank = 0; ! if (token instanceof Import) { rank = 0; ! } else if (token instanceof ImportFrom) { rank = 1; ! } else if (token instanceof ClassDef) { rank = 2; ! } else if (token instanceof FunctionDef) { rank = 3; ! } else if (token instanceof If) { rank = 10; } --- 121,133 ---- public int getClassRanking() { int rank = 0; ! if (token instanceof ImportFromNode) { rank = 0; ! } else if (token instanceof ImportNode) { rank = 1; ! } else if (token instanceof ClassNode) { rank = 2; ! } else if (token instanceof FunctionNode) { rank = 3; ! } else if (token instanceof NameEqualsMainNode) { rank = 10; } Index: ParsedLabelProvider.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/outline/ParsedLabelProvider.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ParsedLabelProvider.java 17 Aug 2003 04:44:22 -0000 1.1 --- ParsedLabelProvider.java 10 Apr 2004 01:48:12 -0000 1.2 *************** *** 8,17 **** import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.graphics.Image; ! import org.python.parser.SimpleNode; ! import org.python.parser.ast.ClassDef; ! import org.python.parser.ast.FunctionDef; ! import org.python.parser.ast.If; ! import org.python.parser.ast.Import; ! import org.python.parser.ast.ImportFrom; import org.python.pydev.ui.ImageCache; import org.python.pydev.ui.UIConstants; --- 8,12 ---- import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.graphics.Image; ! import org.python.pydev.editor.model.*; import org.python.pydev.ui.ImageCache; import org.python.pydev.ui.UIConstants; *************** *** 35,44 **** // returns images based upon element type public Image getImage(Object element) { ! SimpleNode token = ((ParsedItem)element).getToken(); ! if (token instanceof ClassDef) { return imageCache.get(UIConstants.CLASS_ICON); } ! else if (token instanceof FunctionDef) { ! if (((FunctionDef)token).name.startsWith("_")) { return imageCache.get(UIConstants.PRIVATE_METHOD_ICON); } --- 30,39 ---- // returns images based upon element type public Image getImage(Object element) { ! AbstractNode token = ((ParsedItem)element).getToken(); ! if (token instanceof ClassNode) { return imageCache.get(UIConstants.CLASS_ICON); } ! else if (token instanceof FunctionNode) { ! if (((FunctionNode)token).astNode.name.startsWith("_")) { return imageCache.get(UIConstants.PRIVATE_METHOD_ICON); } *************** *** 46,56 **** return imageCache.get(UIConstants.PUBLIC_METHOD_ICON); } ! else if (token instanceof Import) { return imageCache.get(UIConstants.IMPORT_ICON); } ! else if (token instanceof ImportFrom) { return imageCache.get(UIConstants.IMPORT_ICON); } ! else if (token instanceof If) { return imageCache.get(UIConstants.MAIN_FUNCTION_ICON); } --- 41,51 ---- return imageCache.get(UIConstants.PUBLIC_METHOD_ICON); } ! else if (token instanceof ImportNode) { return imageCache.get(UIConstants.IMPORT_ICON); } ! else if (token instanceof ImportFromNode) { return imageCache.get(UIConstants.IMPORT_ICON); } ! else if (token instanceof NameEqualsMainNode) { return imageCache.get(UIConstants.MAIN_FUNCTION_ICON); } Index: RawPartitionModel.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/outline/RawPartitionModel.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** RawPartitionModel.java 5 Mar 2004 22:04:44 -0000 1.3 --- RawPartitionModel.java 10 Apr 2004 01:48:12 -0000 1.4 *************** *** 13,19 **** import org.eclipse.jface.text.IDocumentPartitioningListener; import org.eclipse.jface.text.Position; - import org.eclipse.jface.text.Region; import org.eclipse.jface.text.rules.DefaultPartitioner; import org.eclipse.jface.viewers.StructuredSelection; --- 13,19 ---- import org.eclipse.jface.text.IDocumentPartitioningListener; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.rules.DefaultPartitioner; import org.eclipse.jface.viewers.StructuredSelection; + import org.python.pydev.editor.model.AbstractNode; *************** *** 113,123 **** // IOutlineModel API ! public SelectionPosition getSelectionPosition(StructuredSelection sel) { ! Region r = null; ! if(sel.size() == 1) { // only sync the editing view if it is a single-selection ! Position p = (Position)sel.getFirstElement(); ! r = new Region(p.offset, p.length); ! } ! return new SelectionPosition(r); } --- 113,120 ---- // IOutlineModel API ! public AbstractNode getSelectionPosition(StructuredSelection sel) { ! // we do not have it, broken in Outline rewrite ! System.err.println("RawOutlineModel can't navigate right now"); ! return null; } Index: ParsedModel.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/outline/ParsedModel.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** ParsedModel.java 5 Mar 2004 22:04:43 -0000 1.3 --- ParsedModel.java 10 Apr 2004 01:48:12 -0000 1.4 *************** *** 10,16 **** import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.widgets.Display; ! import org.python.parser.SimpleNode; ! import org.python.pydev.parser.IParserListener; ! import org.python.pydev.parser.PyParser; /** --- 10,16 ---- import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.widgets.Display; ! import org.python.pydev.editor.PyEdit; ! import org.python.pydev.editor.model.AbstractNode; ! import org.python.pydev.editor.model.IModelListener; /** *************** *** 20,26 **** public class ParsedModel implements IOutlineModel { ! PyParser parser; PyOutlinePage outline; ! IParserListener parserListener; ParsedItem root = null; // A list of top nodes in this document. Used as a tree root --- 20,26 ---- public class ParsedModel implements IOutlineModel { ! PyEdit editor; PyOutlinePage outline; ! IModelListener modelListener; ParsedItem root = null; // A list of top nodes in this document. Used as a tree root *************** *** 30,35 **** * @param parser */ ! public ParsedModel(PyOutlinePage outline, PyParser parser) { ! this.parser = parser; this.outline = outline; --- 30,35 ---- * @param parser */ ! public ParsedModel(PyOutlinePage outline, PyEdit editor) { ! this.editor = editor; this.outline = outline; *************** *** 38,44 **** // Tell parser that we want to know about all the changes // make sure that the changes are propagated on the main thread ! parserListener = new IParserListener() { ! public void parserChanged(SimpleNode pyRoot) { ! final SimpleNode myRoot = pyRoot; Display.getDefault().syncExec( new Runnable() { public void run() { --- 38,44 ---- // Tell parser that we want to know about all the changes // make sure that the changes are propagated on the main thread ! modelListener = new IModelListener() { ! public void modelChanged(AbstractNode root) { ! final AbstractNode myRoot = root; Display.getDefault().syncExec( new Runnable() { public void run() { *************** *** 46,68 **** setRoot(new ParsedItem(null, myRoot)); } ! }); ! } ! public void parserError(Throwable error) { ! final Throwable myError = error; ! Display.getDefault().syncExec(new Runnable() { ! public void run() { ! setError(myError); ! } ! }); ! setError(error); } }; ! parser.addParseListener(parserListener); ! ! root = new ParsedItem(null, parser.getRoot()); } public void dispose() { ! parser.removeParseListener(parserListener); } --- 46,58 ---- setRoot(new ParsedItem(null, myRoot)); } ! }); } }; ! root = new ParsedItem(null, editor.getPythonModel()); ! editor.addModelListener(modelListener); } public void dispose() { ! editor.removeModelListener(modelListener); } *************** *** 117,121 **** else { ! System.out.println("No old root in ParsedModel!"); } } --- 107,111 ---- else { ! System.out.println("No old model root?"); } } *************** *** 127,137 **** /* */ ! public SelectionPosition getSelectionPosition(StructuredSelection sel) { ! SelectionPosition position = null; if(sel.size() == 1) { // only sync the editing view if it is a single-selection ParsedItem p = (ParsedItem)sel.getFirstElement(); ! position = p.getPosition(); } ! return position; } --- 117,126 ---- /* */ ! public AbstractNode getSelectionPosition(StructuredSelection sel) { if(sel.size() == 1) { // only sync the editing view if it is a single-selection ParsedItem p = (ParsedItem)sel.getFirstElement(); ! return p.getToken(); } ! return null; } Index: IOutlineModel.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/outline/IOutlineModel.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** IOutlineModel.java 5 Mar 2004 22:04:44 -0000 1.4 --- IOutlineModel.java 10 Apr 2004 01:48:12 -0000 1.5 *************** *** 7,10 **** --- 7,11 ---- import org.eclipse.jface.viewers.StructuredSelection; + import org.python.pydev.editor.model.AbstractNode; /** *************** *** 32,35 **** * @return Point that contains line/column, or item to be selected */ ! SelectionPosition getSelectionPosition(StructuredSelection sel); } --- 33,36 ---- * @return Point that contains line/column, or item to be selected */ ! AbstractNode getSelectionPosition(StructuredSelection sel); } |