[Pydev-cvs] org.python.pydev/src/org/python/pydev/editor/model ItemPointer.java,NONE,1.1 AttributeNo
Brought to you by:
fabioz
From: Aleksandar T. <at...@us...> - 2004-04-15 23:19:32
|
Update of /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16009/src/org/python/pydev/editor/model Modified Files: AbstractNode.java NameEqualsMainNode.java LocalNode.java ModelUtils.java ModuleNode.java ImportNode.java FunctionCallNode.java ClassNode.java FunctionNode.java Scope.java ModelMaker.java LengthEstimator.java ImportFromNode.java ImportAlias.java Added Files: ItemPointer.java AttributeNode.java Log Message: More model code. Hyperlinks on function calls and imports now work. had to pull interpreter editor from PydevDebug plugin into this one since we needed interpreter locaiton for include paths. Model got extensive changes. Scopes are now used in the code. General code cleanup everywehre. Added findFunctionDefinition functionality with hyperlinks Added the ability to open external files (for external hyperlinks) Index: ModelMaker.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/ModelMaker.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ModelMaker.java 10 Apr 2004 01:48:13 -0000 1.1 --- ModelMaker.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 6,10 **** --- 6,14 ---- package org.python.pydev.editor.model; + import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IStatus; + import org.eclipse.jface.text.BadLocationException; + import org.eclipse.jface.text.IDocument; + import org.eclipse.jface.text.IRegion; import org.python.parser.SimpleNode; import org.python.parser.ast.*; *************** *** 13,16 **** --- 17,21 ---- /** * Creates the model from the AST tree. + * uses PopulateModel visitor pattern to create the tree. */ public class ModelMaker { *************** *** 21,27 **** * */ ! public static ModuleNode createModel(SimpleNode root, int lines, int cols) { ! ModuleNode n = new ModuleNode(null, lines, cols); ! PopulateModel populator = new PopulateModel(root, n); try { root.accept(populator); --- 26,40 ---- * */ ! public static ModuleNode createModel(SimpleNode root, IDocument doc, IFile file) { ! int lastLine = doc.getNumberOfLines(); ! int lineLength = 255; ! try { ! IRegion r = doc.getLineInformation(lastLine-1); ! lineLength = r.getLength(); ! } catch (BadLocationException e1) { ! PydevPlugin.log(IStatus.ERROR, "Unexpected error getting last line", e1); ! } ! ModuleNode n = new ModuleNode(file, lastLine, lineLength); ! PopulateModel populator = new PopulateModel(root, n, doc); try { root.accept(populator); *************** *** 34,43 **** /** ! * Problems this class is trying to solve: ! * ! * - figuring out the end position of the node. AST only has starting position, ! * so we need to heuristically find the end of it ! * * */ static class PopulateModel extends VisitorBase { --- 47,55 ---- /** ! * Create the model by traversing AST tree. * + * visit* functions are required by visitor patters. + * When the pattern finds something interesting, it calls process* which + * create the model. */ static class PopulateModel extends VisitorBase { *************** *** 45,61 **** SimpleNode root; AbstractNode parent; ! public PopulateModel(SimpleNode root, AbstractNode parent) { this.root = root; this.parent = parent; } void processAliases(AbstractNode parent, aliasType[] nodes) { for (int i=0; i<nodes.length; i++) ! new ImportAlias(parent, nodes[i]); } void processImport(Import node) { ! ImportNode newNode = new ImportNode(parent, node); // have to traverse children manually to find all imports processAliases(newNode, node.names); --- 57,89 ---- SimpleNode root; AbstractNode parent; + IDocument doc; ! public PopulateModel(SimpleNode root, AbstractNode parent, IDocument doc) { this.root = root; this.parent = parent; + this.doc = doc; + } + + private String getLineText(SimpleNode node) { + try { + IRegion lineInfo = doc.getLineInformation(node.beginLine -1); + return doc.get(lineInfo.getOffset(), lineInfo.getLength()); + } catch (BadLocationException e) { + PydevPlugin.log(IStatus.ERROR, "Unexpected getLineText error", e); + } + return ""; } + /** + * processAliases creates Import tokens. + * import os, sys would create 2 aliases + */ void processAliases(AbstractNode parent, aliasType[] nodes) { for (int i=0; i<nodes.length; i++) ! new ImportAlias(parent, nodes[i], getLineText(nodes[i])); } void processImport(Import node) { ! ImportNode newNode = new ImportNode(parent, node, getLineText(node)); // have to traverse children manually to find all imports processAliases(newNode, node.names); *************** *** 63,67 **** void processImportFrom(ImportFrom node) { ! ImportFromNode newNode = new ImportFromNode(parent, node); // have to traverse children manually to find all imports processAliases(newNode, node.names); --- 91,95 ---- void processImportFrom(ImportFrom node) { ! ImportFromNode newNode = new ImportFromNode(parent, node, getLineText(node)); // have to traverse children manually to find all imports processAliases(newNode, node.names); *************** *** 71,75 **** ClassNode newNode = new ClassNode(parent, node); // traverse inside the class definition ! PopulateModel populator = new PopulateModel(node, newNode); try { node.traverse(populator); --- 99,103 ---- ClassNode newNode = new ClassNode(parent, node); // traverse inside the class definition ! PopulateModel populator = new PopulateModel(node, newNode, doc); try { node.traverse(populator); *************** *** 81,87 **** void processFunctionDef(FunctionDef node) { ! FunctionNode newNode = new FunctionNode(parent, node); // traverse inside the function definition ! PopulateModel populator = new PopulateModel(node, newNode); try { node.traverse(populator); --- 109,115 ---- void processFunctionDef(FunctionDef node) { ! FunctionNode newNode = new FunctionNode(parent, node, getLineText(node)); // traverse inside the function definition ! PopulateModel populator = new PopulateModel(node, newNode, doc); try { node.traverse(populator); *************** *** 94,103 **** void processLocal(Name node) { if (!LocalNode.isBuiltin(node.id)) ! new LocalNode(parent, node); } void processFunctionCall(Call node) { ! FunctionCallNode newNode = new FunctionCallNode(parent, node); ! PopulateModel populator = new PopulateModel(node, newNode); try { node.traverse(populator); --- 122,131 ---- void processLocal(Name node) { if (!LocalNode.isBuiltin(node.id)) ! new LocalNode(parent, node, getLineText(node)); } void processFunctionCall(Call node) { ! FunctionCallNode newNode = new FunctionCallNode(parent, node, getLineText(node)); ! PopulateModel populator = new PopulateModel(node, newNode, doc); try { node.traverse(populator); *************** *** 108,115 **** void processMain(If node) { ! NameEqualsMainNode newNode = new NameEqualsMainNode(parent, node); } protected Object unhandled_node(SimpleNode node) throws Exception { return null; } --- 136,148 ---- void processMain(If node) { ! new NameEqualsMainNode(parent, node); ! } ! ! private void processAttribute(Attribute node) { ! new AttributeNode(parent, node, getLineText(node)); } protected Object unhandled_node(SimpleNode node) throws Exception { + // System.err.println("Unhandled: " + node.getClass().toString() + " L:" + Integer.toString(node.beginLine)); return null; } *************** *** 166,173 **** && ((Str)compareNode.comparators[0]).s.equals("__main__")) processMain(node); - return null; } return super.visitIf(node); } } } --- 199,211 ---- && ((Str)compareNode.comparators[0]).s.equals("__main__")) processMain(node); } return super.visitIf(node); } + + public Object visitAttribute(Attribute node) throws Exception { + processAttribute(node); + super.visitAttribute(node); + return null; // do not want to visit its children? + } } } Index: ModelUtils.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/ModelUtils.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ModelUtils.java 10 Apr 2004 01:48:13 -0000 1.1 --- ModelUtils.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 6,12 **** --- 6,15 ---- package org.python.pydev.editor.model; + import java.io.File; import java.util.ArrayList; + import java.util.Comparator; import java.util.Iterator; + import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.text.BadLocationException; *************** *** 16,23 **** /** ! * Utility functions: querying/conversion */ public class ModelUtils { public static AbstractNode getElement(AbstractNode root, int offset, IDocument doc, int properties) { try { --- 19,42 ---- /** ! * Utility functions: querying/conversion of the model. ! * ! * The model is ordered by position in the file, and can be traversed ! * with {@link #getNextNode} and {@link #getPreviousNode}. ! * ! * The ordering looks like this: ! * <pre> ! * 0 ! * / \ ! * / \ ! * 1 4 ! * / \ /\ ! * 2 3 5 6 ! * </pre> */ public class ModelUtils { + /** + * See the getElement(AbstractNode root, Location loc, int properties) comment. + */ public static AbstractNode getElement(AbstractNode root, int offset, IDocument doc, int properties) { try { *************** *** 32,36 **** /** ! * Depth-first search for a node that spans given location * @param root: node to start the search with * @param loc: location we are looking for --- 51,55 ---- /** ! * Depth-first search for a node that spans given location. * @param root: node to start the search with * @param loc: location we are looking for *************** *** 145,148 **** --- 164,170 ---- } + /** + * Tree traversal, get next node. + */ public static AbstractNode getNextNode(AbstractNode node) { if (node == null) *************** *** 154,156 **** --- 176,213 ---- return getNextNodeHelper(node.getParent(), node); } + + /** + * Finds where the given node is defined. + * @return TRICKY: null if nothing found. Otherwise, an array list of + * If found first element is the IFile + * second element is start of the + */ + public static ArrayList findDefinition(AbstractNode node) { + IFile file; + ArrayList retVal = new ArrayList(); + // simple function calls + // ex: simpleCall() + if (node instanceof LocalNode && + node.getParent() instanceof FunctionCallNode) { + ArrayList funcCalls = node.getScope().findFunctionCalls(node.getName(), true, + new Comparator() { + public int compare(Object token, Object funcCall) { + return ((String)token).compareTo(((AbstractNode)funcCall).getName()); + } + }); + for (Iterator i = funcCalls.iterator(); i.hasNext();) { + FunctionNode funcNode = (FunctionNode)i.next(); + retVal.add(new ItemPointer(funcNode.getFile(), funcNode.getStart(), funcNode.getEnd())); + } + } else if (node instanceof ImportAlias) { + // imports: + // import sys + File myImport = node.getScope().findImport(node.getName(), node.getFile()); + if (myImport != null) + retVal.add(new ItemPointer(myImport)); + }else if (node instanceof AttributeNode) { + // method calls. ex: self.break_here() + } + return retVal; + } } Index: LengthEstimator.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/LengthEstimator.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** LengthEstimator.java 10 Apr 2004 01:48:13 -0000 1.1 --- LengthEstimator.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 68,72 **** public Object visitBinOp(BinOp node) throws Exception { ! System.out.println("lenVisitBinOp:" + node.toString("")); return null; } --- 68,72 ---- public Object visitBinOp(BinOp node) throws Exception { ! // System.out.println("lenVisitBinOp:" + node.toString("")); return null; } *************** *** 216,220 **** public Object visitNum(Num node) throws Exception { ! System.out.println("lenVisitNum:" + node.toString("")); return null; } --- 216,220 ---- public Object visitNum(Num node) throws Exception { ! // System.out.println("lenVisitNum:" + node.toString("")); return null; } *************** *** 258,262 **** public Object visitStr(Str node) throws Exception { ! System.out.println("lenVisitStr:" + node.toString("")); return null; } --- 258,262 ---- public Object visitStr(Str node) throws Exception { ! // System.out.println("lenVisitStr:" + node.toString("")); return null; } *************** *** 264,268 **** public Object visitSubscript(Subscript node) throws Exception { ! System.out.println("lenVisitSubscript:" + node.toString("")); return null; } --- 264,268 ---- public Object visitSubscript(Subscript node) throws Exception { ! // System.out.println("lenVisitSubscript:" + node.toString("")); return null; } *************** *** 288,292 **** public Object visitTuple(Tuple node) throws Exception { ! System.out.println("lenVisitTuple:" + node.toString("")); return null; } --- 288,292 ---- public Object visitTuple(Tuple node) throws Exception { ! // System.out.println("lenVisitTuple:" + node.toString("")); return null; } Index: ImportAlias.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/ImportAlias.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ImportAlias.java 10 Apr 2004 01:48:13 -0000 1.1 --- ImportAlias.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 17,26 **** aliasType astNode; ! public ImportAlias(AbstractNode parent, aliasType astNode) { super(parent); this.astNode = astNode; setStart(new Location(astNode.beginLine - 1, astNode.beginColumn - 1)); setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn - 1 + astNode.name.length())); properties = PROP_CLICKABLE; } } --- 17,32 ---- aliasType astNode; ! public ImportAlias(AbstractNode parent, aliasType astNode, String lineText) { super(parent); this.astNode = astNode; setStart(new Location(astNode.beginLine - 1, astNode.beginColumn - 1)); setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn - 1 + astNode.name.length())); + fixColumnLocation(start, lineText); + fixColumnLocation(end, lineText); properties = PROP_CLICKABLE; } + + public String getName() { + return astNode.name; + } } Index: FunctionCallNode.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/FunctionCallNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** FunctionCallNode.java 10 Apr 2004 01:48:13 -0000 1.1 --- FunctionCallNode.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 19,26 **** * @param parent */ ! public FunctionCallNode(AbstractNode parent, Call astNode) { super(parent); this.astNode = astNode; ! this.setStart(new Location(astNode.beginLine - 1, astNode.beginColumn)); LengthEstimator estimate = new LengthEstimator(); try { --- 19,26 ---- * @param parent */ ! public FunctionCallNode(AbstractNode parent, Call astNode, String lineText) { super(parent); this.astNode = astNode; ! this.setStart(new Location(astNode.beginLine - 1, astNode.beginColumn - 1)); LengthEstimator estimate = new LengthEstimator(); try { *************** *** 31,35 **** --- 31,41 ---- this.setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn + estimate.getLength())); + fixColumnLocation(start, lineText); + fixColumnLocation(end, lineText); properties = PROP_CLICKABLE; } + + public String getName() { + return null; + } } Index: LocalNode.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/LocalNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** LocalNode.java 10 Apr 2004 01:48:13 -0000 1.1 --- LocalNode.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 25,42 **** * @param parent */ ! public LocalNode(AbstractNode parent, Name astNode) { super(parent); this.astNode = astNode; ! this.setStart(new Location(astNode.beginLine - 1, astNode.beginColumn)); ! this.setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn + astNode.id.length())); parent.getScope().addLocalDefinition(this); properties = PROP_CLICKABLE; } public String toString() { return super.toString() + astNode.id; } - - public class PredefinedNameException extends Exception { - } } --- 25,45 ---- * @param parent */ ! public LocalNode(AbstractNode parent, Name astNode, String lineText) { super(parent); this.astNode = astNode; ! this.setStart(new Location(astNode.beginLine - 1, astNode.beginColumn-1)); ! this.setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn -1+ astNode.id.length())); ! fixColumnLocation(start, lineText); ! fixColumnLocation(end, lineText); parent.getScope().addLocalDefinition(this); properties = PROP_CLICKABLE; } + public String getName() { + return astNode.id; + } + public String toString() { return super.toString() + astNode.id; } } Index: ImportNode.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/ImportNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ImportNode.java 10 Apr 2004 01:48:13 -0000 1.1 --- ImportNode.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 15,19 **** public Import astNode; ! public ImportNode(AbstractNode parent, Import astNode) { super(parent); this.astNode = astNode; --- 15,19 ---- public Import astNode; ! public ImportNode(AbstractNode parent, Import astNode, String lineText) { super(parent); this.astNode = astNode; *************** *** 21,26 **** setStart(new Location(astNode.beginLine - 1, astNode.beginColumn - 8)); setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn - 2)); } ! } --- 21,30 ---- setStart(new Location(astNode.beginLine - 1, astNode.beginColumn - 8)); setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn - 2)); + fixColumnLocation(start, lineText); + fixColumnLocation(end, lineText); } ! public String getName() { ! return "Import has a list of ImportAliases as its children"; ! } } Index: ModuleNode.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/ModuleNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ModuleNode.java 10 Apr 2004 01:48:13 -0000 1.1 --- ModuleNode.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 6,9 **** --- 6,11 ---- package org.python.pydev.editor.model; + import org.eclipse.core.resources.IFile; + /** * Top-level node representing a python module. *************** *** 14,25 **** Scope scope; ! public ModuleNode(AbstractNode parent, int lines, int cols) { ! super(parent); scope = new Scope(this); // FileNode always spans the entire file this.start = Location.MIN_LOCATION; this.end = new Location(lines, cols); } public Scope getScope() { --- 16,38 ---- Scope scope; + IFile file; ! public ModuleNode(IFile file, int lines, int cols) { ! super(null); scope = new Scope(this); // FileNode always spans the entire file + this.file = file; this.start = Location.MIN_LOCATION; this.end = new Location(lines, cols); } + + public String getName() { + // TODO module needs a name, probably a file it comes from + return "module"; + } + + public IFile getFile() { + return file; + } public Scope getScope() { Index: ImportFromNode.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/ImportFromNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ImportFromNode.java 10 Apr 2004 01:48:13 -0000 1.1 --- ImportFromNode.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 17,26 **** public ImportFrom astNode; ! public ImportFromNode(AbstractNode parent, ImportFrom astNode) { super(parent); this.astNode = astNode; setStart(new Location(astNode.beginLine - 1, astNode.beginColumn - 1)); setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn -1 + astNode.module.length())); properties = PROP_CLICKABLE; } } --- 17,32 ---- public ImportFrom astNode; ! public ImportFromNode(AbstractNode parent, ImportFrom astNode, String lineText) { super(parent); this.astNode = astNode; setStart(new Location(astNode.beginLine - 1, astNode.beginColumn - 1)); setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn -1 + astNode.module.length())); + fixColumnLocation(start, lineText); + fixColumnLocation(end, lineText); properties = PROP_CLICKABLE; } + + public String getName() { + return astNode.module; + } } --- NEW FILE: AttributeNode.java --- /* * Author: atotic * Created on Apr 14, 2004 * License: Common Public License v1.0 */ package org.python.pydev.editor.model; import org.python.parser.ast.Attribute; /** * self.a.b.c.d => a,b,c & d are attributes. */ public class AttributeNode extends AbstractNode { public Attribute astNode; public AttributeNode(AbstractNode parent, Attribute astNode, String lineText) { super(parent); this.astNode = astNode; this.setStart(new Location(astNode.beginLine - 1, astNode.beginColumn-1)); this.setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn -1 + astNode.attr.length())); fixColumnLocation(start, lineText); fixColumnLocation(end, lineText); // HACK alert // For the final attribute the location produced by AST is wrong (probably intentionally) // So I'll resort to desperate measure of doing a text search to find a matching string // this will work sometimes. if (astNode.beginColumn <= astNode.value.beginColumn) { Location temp = new Location(0, astNode.value.beginColumn -1); fixColumnLocation(temp, lineText); int grep = lineText.indexOf(astNode.attr, temp.column+1); if (grep != -1 && grep > start.column) { start.column = grep; end.column = start.column + astNode.attr.length(); } } properties = PROP_CLICKABLE; } public String getName() { return astNode.attr; } public String toString() { return super.toString()+ astNode.attr; } } Index: FunctionNode.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/FunctionNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** FunctionNode.java 10 Apr 2004 01:48:13 -0000 1.1 --- FunctionNode.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 16,28 **** Scope scope; ! public FunctionNode(AbstractNode parent, FunctionDef node) { super(parent); this.astNode = node; scope = new Scope(this); setStart(new Location(astNode.beginLine - 1, astNode.beginColumn + 3)); setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn + 3 + astNode.name.length())); properties = PROP_CLICKABLE; } public Scope getScope() { return scope; --- 16,36 ---- Scope scope; ! public FunctionNode(AbstractNode parent, FunctionDef node, String lineText) { super(parent); this.astNode = node; scope = new Scope(this); + parent.getScope().addFunctionDefinition(this); + setStart(new Location(astNode.beginLine - 1, astNode.beginColumn + 3)); setEnd(new Location(astNode.beginLine - 1, astNode.beginColumn + 3 + astNode.name.length())); + fixColumnLocation(start, lineText); + fixColumnLocation(end, lineText); properties = PROP_CLICKABLE; } + public String getName() { + return astNode.name; + } + public Scope getScope() { return scope; Index: NameEqualsMainNode.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/NameEqualsMainNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** NameEqualsMainNode.java 10 Apr 2004 01:48:13 -0000 1.1 --- NameEqualsMainNode.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 21,23 **** --- 21,27 ---- this.setEnd(new Location(astNode.beginLine, astNode.beginColumn + 22)); } + + public String getName() { + return "if __name__ equals main"; + } } Index: Scope.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/Scope.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Scope.java 10 Apr 2004 01:48:13 -0000 1.1 --- Scope.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 6,14 **** package org.python.pydev.editor.model; import java.util.ArrayList; import java.util.Iterator; /** ! * Scope represents scope where local variables belong to. * * There is a scope hierarchy: --- 6,22 ---- package org.python.pydev.editor.model; + import java.io.File; import java.util.ArrayList; + import java.util.Comparator; import java.util.Iterator; + import org.eclipse.core.resources.IFile; + import org.eclipse.core.runtime.IPath; + import org.python.pydev.plugin.PydevPrefs; + + /** ! * Scope is where definitions of locals/classes/functions go in a namespace. ! * Every AbstractNode has a scope. * * There is a scope hierarchy: *************** *** 23,27 **** private AbstractNode end; private Scope parent; ! private ArrayList children; public Scope(AbstractNode start) { --- 31,38 ---- private AbstractNode end; private Scope parent; ! ! // Lists of elements defined inside this this scope. ! private ArrayList children; // array of LocalNodes ! private ArrayList functions; // array of FunctionCallNodes public Scope(AbstractNode start) { *************** *** 62,65 **** --- 73,82 ---- } + void addFunctionDefinition(FunctionNode newDef) { + if (functions == null) + functions = new ArrayList(); + functions.add(newDef); + } + public Location getStart() { return start.getStart(); *************** *** 86,88 **** --- 103,177 ---- this.end = trueEndNode; } + + /** + * @param name: function name + * @param c: comparator to test for. + * @return an ArrayList of ItemPointers to the function definitions. + * each returned item will test as equal in c.compare(token, item); + * null is never returned, there will be an empty array if none were found. + * + * Usage: + scope.findFunctionCalls("FunctionName", true, + new Comparator() { + public int compare(Object token, Object funcCall) { + return ((String)token).compareTo(((AbstractNode)funcCall).getName()); + + */ + + public ArrayList findFunctionCalls(Object token, boolean recursive, Comparator c) { + ArrayList retVal = new ArrayList(); + // traverse our definitions + if (functions != null) { + Iterator i = functions.iterator(); + while (i.hasNext()) { + Object item = i.next(); + if (c.compare(token, item) == 0) + retVal.add(item); + } + } + // now traverse parents + ArrayList ancestors = null; + if (recursive) + if (parent != null) + ancestors = parent.findFunctionCalls(token, recursive, c); + if (ancestors != null) + retVal.addAll(ancestors); + return retVal; + } + + /** + * get all the import files + * @param startingPoint: a file to start searching from + * @return an ordered ArrayList of File of all import paths for the project. + */ + private ArrayList getImportPaths(IFile startingPoint) { + ArrayList retVal = new ArrayList(); + // 1) the directory where the file is + if (startingPoint != null) { + IPath fileDir = startingPoint.getLocation().removeLastSegments(1); + retVal.add(fileDir.toFile()); + } + // 2) interpreter/Lib + String interpreter = PydevPrefs.getInterpreters()[0]; + File interpreterFile = new File(interpreter); + String parent = interpreterFile.getParent(); + if (parent != null) + retVal.add(new File(parent, "Lib")); + return retVal; + } + + /** + * Find a file "name.py", searching the import include path + * @return ArrayList of File objects that match. + */ + public File findImport(String name, IFile startAt) { + ArrayList importPaths = getImportPaths(startAt); + for (Iterator i= importPaths.iterator();i.hasNext();) { + File dir = (File)i.next(); + File testFile = new File(dir, name + ".py"); + if (testFile.exists()) + return testFile; + } + return null; + } } --- NEW FILE: ItemPointer.java --- /* * Author: atotic * Created on Apr 14, 2004 * License: Common Public License v1.0 */ package org.python.pydev.editor.model; /** * * TODO Comment this class */ public class ItemPointer { public Object file; // IFile or File... public Location start; public Location end; public ItemPointer(Object file) { this(file, new Location(), new Location()); } public ItemPointer(Object file, Location start, Location end) { this.file = file; this.start = start; this.end = end; } } Index: ClassNode.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/ClassNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ClassNode.java 10 Apr 2004 01:48:13 -0000 1.1 --- ClassNode.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 25,28 **** --- 25,32 ---- } + public String getName() { + return astNode.name; + } + public Scope getScope() { return scope; Index: AbstractNode.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/model/AbstractNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** AbstractNode.java 10 Apr 2004 01:48:13 -0000 1.1 --- AbstractNode.java 15 Apr 2004 23:19:21 -0000 1.2 *************** *** 8,11 **** --- 8,15 ---- import java.util.ArrayList; + import org.eclipse.core.resources.IFile; + import org.eclipse.core.runtime.IStatus; + import org.python.pydev.plugin.PydevPlugin; + /** * ModelNode is a superclass of all nodes. *************** *** 15,19 **** * For example, clickable nodes have PROP_CLICKABLE set. */ ! public class AbstractNode { static ArrayList emptyChildList = new ArrayList(); // we keep an empty list around for efficiency --- 19,23 ---- * For example, clickable nodes have PROP_CLICKABLE set. */ ! public abstract class AbstractNode { static ArrayList emptyChildList = new ArrayList(); // we keep an empty list around for efficiency *************** *** 91,93 **** --- 95,135 ---- return getClass().toString() + " " + start.toString() + end.toString(); } + + /** + * Subclasses should override. This gets the python string. + */ + public abstract String getName(); + + public IFile getFile() { + return parent.getFile(); + } + + /** + * This function is a heuristic solution for the way jython & TextEditor + * deal with column numbers. + * + * jython's parser converts tabs to spaces internally. + * When it reports the column, it reports the column after the spaces + * have been converted to tabs. So in "\tFunc()", func starts in column + * 5 according to jython's parser, and in column 1 according to text editor. + * + * This fix tries to convert jython's column numbers to those that work for editor. + * To do this, we get the whole line where location was defined, and + * substract the spaces assumed by jython (8 per tab). + */ + public void fixColumnLocation(Location loc, String lineText) { + int where = 0; + int tabCount = 0; + where = lineText.indexOf("\t", where); + while (where != -1 && where <= loc.column) { + where = lineText.indexOf("\t", where+1); + tabCount++; + } + if (tabCount > 0) + loc.column = loc.column - tabCount * 7; + if (loc.column < 0) { + loc.column = 0; + PydevPlugin.log(IStatus.ERROR, "Unexpected columnFixLocation error", null); + } + } } |