~vil/pydev/upstream

« back to all changes in this revision

Viewing changes to org.python.pydev/PySrc/ThirdParty/brm/bike/query/findReferences.py

  • Committer: Vladimír Lapáček
  • Date: 2006-08-30 18:38:44 UTC
  • Revision ID: vladimir.lapacek@gmail.com-20060830183844-f4d82c1239a7770a
Initial import of upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from __future__ import generators
 
2
from bike.globals import *
 
3
from bike.parsing.fastparserast import Module, Class, Function, getRoot, Instance
 
4
from bike.query.common import Match, MatchFinder,\
 
5
     getScopeForLine, indexToCoordinates, \
 
6
     translateSourceCoordsIntoASTNode, scanScopeForMatches,\
 
7
     globalScanForMatches, isAMethod, convertNodeToMatchObject
 
8
from compiler.ast import AssName,Name,Getattr,AssAttr
 
9
import compiler
 
10
from findDefinition import findDefinitionFromASTNode
 
11
from bike.query.getTypeOf import getTypeOfExpr, UnfoundType
 
12
from bike.query.relationships import getRootClassesOfHierarchy
 
13
from bike import log
 
14
from bike.parsing.load import getSourceNode
 
15
 
 
16
 
 
17
class CouldntFindDefinitionException(Exception):
 
18
    pass
 
19
 
 
20
def findReferencesIncludingDefn(filename,lineno,col):
 
21
    return findReferences(filename,lineno,col,1)
 
22
 
 
23
 
 
24
def findReferences(filename,lineno,col,includeDefn=0):
 
25
    sourcenode = getSourceNode(filename)
 
26
    node = translateSourceCoordsIntoASTNode(filename,lineno,col)
 
27
    assert node is not None
 
28
    scope,defnmatch = getDefinitionAndScope(sourcenode,lineno,node)
 
29
 
 
30
    try:
 
31
        for match in findReferencesIncludingDefn_impl(sourcenode,node,
 
32
                                                      scope,defnmatch):
 
33
            if not includeDefn and match == defnmatch: 
 
34
                continue        # don't return definition
 
35
            else:
 
36
                yield match
 
37
    except CouldntFindDefinitionException:
 
38
        raise CouldntFindDefinitionException("Could not find definition. Please locate manually (maybe using find definition) and find references from that")
 
39
 
 
40
def findReferencesIncludingDefn_impl(sourcenode,node,scope,defnmatch):
 
41
    if isinstance(node,Name) or isinstance(node,AssName):
 
42
        return generateRefsToName(node.name,scope,sourcenode,defnmatch)
 
43
    elif isinstance(node,Getattr) or isinstance(node,AssAttr):
 
44
        exprtype = getTypeOfExpr(scope,node.expr)
 
45
        if exprtype is None or isinstance(exprtype,UnfoundType):
 
46
            raise CouldntFindDefinitionException()
 
47
 
 
48
        if isinstance(exprtype,Instance):
 
49
            exprtype = exprtype.getType()
 
50
            return generateRefsToAttribute(exprtype,node.attrname)
 
51
        
 
52
        else:
 
53
            targetname = node.attrname
 
54
            return globalScanForMatches(sourcenode.filename,
 
55
                                        NameRefFinder(targetname, defnmatch),
 
56
                                        targetname, )
 
57
        if match is not None:
 
58
            return match
 
59
    elif isinstance(node,compiler.ast.Function) or \
 
60
                             isinstance(node,compiler.ast.Class):
 
61
        return handleClassOrFunctionRefs(scope, node, defnmatch)
 
62
    else:
 
63
        assert 0,"Seed to references must be Name,Getattr,Function or Class"
 
64
 
 
65
def handleClassOrFunctionRefs(scope, node, defnmatch):
 
66
    if isAMethod(scope,node):        
 
67
        for ref in generateRefsToAttribute(scope,node.name):
 
68
            yield ref
 
69
    else:
 
70
        #yield convertNodeToMatchObject(node,100)
 
71
        yield defnmatch
 
72
        for ref in generateRefsToName(node.name,scope,
 
73
                                    scope.module.getSourceNode(),
 
74
                                    defnmatch):
 
75
            yield ref
 
76
 
 
77
def getDefinitionAndScope(sourcenode,lineno,node):
 
78
    scope = getScopeForLine(sourcenode,lineno)
 
79
    if scope.getStartLine() == lineno and \
 
80
           scope.matchesCompilerNode(node):  # scope is the node
 
81
        return scope.getParent(), convertNodeToMatchObject(scope,100)
 
82
    defnmatch = findDefinitionFromASTNode(scope,node)
 
83
    if defnmatch is None:
 
84
        raise CouldntFindDefinitionException()
 
85
    scope = getScopeForLine(sourcenode,defnmatch.lineno)
 
86
    return scope,defnmatch
 
87
 
 
88
def generateRefsToName(name,scope,sourcenode,defnmatch):
 
89
    assert scope is not None
 
90
    if isinstance(scope,Function):
 
91
        # search can be limited to scope
 
92
        return scanScopeForMatches(sourcenode,scope,
 
93
                                   NameRefFinder(name,defnmatch),
 
94
                                   name)
 
95
    else:        
 
96
        return globalScanForMatches(sourcenode.filename,
 
97
                                    NameRefFinder(name,defnmatch),
 
98
                                    name)
 
99
 
 
100
 
 
101
class NameRefFinder(MatchFinder):
 
102
    def __init__(self, targetstr,targetMatch):
 
103
        self.targetstr = targetstr
 
104
        self.targetMatch = targetMatch
 
105
        
 
106
    def visitName(self, node):
 
107
        if node.name == self.targetstr:
 
108
            potentualMatch = findDefinitionFromASTNode(self.scope, node)
 
109
            if  potentualMatch is not None and \
 
110
                   potentualMatch == self.targetMatch:
 
111
                self.appendMatch(node.name)
 
112
        self.popWordsUpTo(node.name)
 
113
 
 
114
    visitAssName = visitName
 
115
 
 
116
    def visitFunction(self, node):
 
117
        self.popWordsUpTo(node.name)
 
118
        for arg, default in self.zipArgs(node.argnames, node.defaults):
 
119
            if arg == self.targetstr:
 
120
                self.appendMatch(arg)
 
121
            self.popWordsUpTo(arg)
 
122
            if default is not None:
 
123
                self.visit(default)
 
124
        self.visit(node.code)
 
125
 
 
126
 
 
127
    def visitFrom(self, node):
 
128
        for elem in node.modname.split("."):
 
129
            self.popWordsUpTo(elem)
 
130
            
 
131
        for name, alias in node.names:
 
132
            if name == self.targetstr:
 
133
                if alias is not None:
 
134
                    pretendNode = Name(alias)
 
135
                else:
 
136
                    pretendNode = Name(name)
 
137
                if findDefinitionFromASTNode(self.scope, pretendNode) \
 
138
                                                    == self.targetMatch:
 
139
                    self.appendMatch(name)
 
140
            self.popWordsUpTo(name)
 
141
            if alias is not None:
 
142
                self.popWordsUpTo(alias)
 
143
 
 
144
 
 
145
    def visitGetattr(self, node):        
 
146
        for c in node.getChildNodes():
 
147
            self.visit(c)
 
148
        if node.attrname == self.targetstr:
 
149
            defn = findDefinitionFromASTNode(self.scope, node)
 
150
            if defn is not None and defn == self.targetMatch:
 
151
                self.appendMatch(node.attrname)
 
152
        self.popWordsUpTo(node.attrname)
 
153
 
 
154
 
 
155
    def visitImport(self, node):
 
156
        for name, alias in node.names:
 
157
            if name.split(".")[-1] == self.targetstr:
 
158
                getattr = self.createGetattr(name)
 
159
                if findDefinitionFromASTNode(self.scope, getattr) == self.targetMatch:
 
160
                    self.appendMatch(self.targetstr)
 
161
            for nameelem in name.split("."):
 
162
                self.popWordsUpTo(nameelem)
 
163
            if alias is not None:
 
164
                self.popWordsUpTo(alias)
 
165
 
 
166
    
 
167
    def createGetattr(self,fqn):
 
168
        node = Name(fqn[0])
 
169
        for name in fqn.split(".")[1:]:
 
170
            node = Getattr(node,name)
 
171
        return node
 
172
                           
 
173
def generateRefsToAttribute(classobj,attrname):
 
174
    rootClasses = getRootClassesOfHierarchy(classobj)
 
175
    attrRefFinder = AttrbuteRefFinder(rootClasses,attrname)
 
176
    for ref in globalScanForMatches(classobj.filename, attrRefFinder, attrname):
 
177
        yield ref
 
178
    print >>log.progress,"Done"
 
179
    
 
180
 
 
181
class AttrbuteRefFinder(MatchFinder):
 
182
    def __init__(self,rootClasses,targetAttribute):
 
183
        self.rootClasses = rootClasses
 
184
        self.targetAttributeName = targetAttribute
 
185
 
 
186
    
 
187
    def visitGetattr(self, node):
 
188
        for c in node.getChildNodes():
 
189
            self.visit(c)
 
190
 
 
191
        if node.attrname == self.targetAttributeName:
 
192
            exprtype = getTypeOfExpr(self.scope,node.expr)            
 
193
 
 
194
            if isinstance(exprtype,Instance) and \
 
195
                 self._isAClassInTheSameHierarchy(exprtype.getType()):
 
196
                self.appendMatch(self.targetAttributeName)
 
197
            elif isinstance(exprtype,UnfoundType) or \
 
198
                 exprtype is None:   # couldn't find type, so not sure
 
199
                self.appendMatch(self.targetAttributeName,50)
 
200
            else:
 
201
                pass # definately not a match
 
202
        self.popWordsUpTo(node.attrname)
 
203
 
 
204
    visitAssAttr = visitGetattr
 
205
 
 
206
    def visitFunction(self,node):  # visit methods
 
207
        if node.name == self.targetAttributeName:
 
208
            parentScope = self.scope.getParent()
 
209
            #print parentScope
 
210
            #print self.targetClasses
 
211
            if isinstance(parentScope,Class) and \
 
212
                   self._isAClassInTheSameHierarchy(parentScope):
 
213
                self.appendMatch(node.name)
 
214
 
 
215
        for c in node.getChildNodes():
 
216
            self.visit(c)
 
217
        
 
218
    def _isAClassInTheSameHierarchy(self,classobj):
 
219
        #return classobj in self.targetClasses
 
220
        targetRootClasses = getRootClassesOfHierarchy(classobj)
 
221
        for rootclass in self.rootClasses:
 
222
            if rootclass in targetRootClasses:
 
223
                return True
 
224
        return False