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
10
from findDefinition import findDefinitionFromASTNode
11
from bike.query.getTypeOf import getTypeOfExpr, UnfoundType
12
from bike.query.relationships import getRootClassesOfHierarchy
14
from bike.parsing.load import getSourceNode
17
class CouldntFindDefinitionException(Exception):
20
def findReferencesIncludingDefn(filename,lineno,col):
21
return findReferences(filename,lineno,col,1)
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)
31
for match in findReferencesIncludingDefn_impl(sourcenode,node,
33
if not includeDefn and match == defnmatch:
34
continue # don't return definition
37
except CouldntFindDefinitionException:
38
raise CouldntFindDefinitionException("Could not find definition. Please locate manually (maybe using find definition) and find references from that")
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()
48
if isinstance(exprtype,Instance):
49
exprtype = exprtype.getType()
50
return generateRefsToAttribute(exprtype,node.attrname)
53
targetname = node.attrname
54
return globalScanForMatches(sourcenode.filename,
55
NameRefFinder(targetname, defnmatch),
59
elif isinstance(node,compiler.ast.Function) or \
60
isinstance(node,compiler.ast.Class):
61
return handleClassOrFunctionRefs(scope, node, defnmatch)
63
assert 0,"Seed to references must be Name,Getattr,Function or Class"
65
def handleClassOrFunctionRefs(scope, node, defnmatch):
66
if isAMethod(scope,node):
67
for ref in generateRefsToAttribute(scope,node.name):
70
#yield convertNodeToMatchObject(node,100)
72
for ref in generateRefsToName(node.name,scope,
73
scope.module.getSourceNode(),
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)
84
raise CouldntFindDefinitionException()
85
scope = getScopeForLine(sourcenode,defnmatch.lineno)
86
return scope,defnmatch
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),
96
return globalScanForMatches(sourcenode.filename,
97
NameRefFinder(name,defnmatch),
101
class NameRefFinder(MatchFinder):
102
def __init__(self, targetstr,targetMatch):
103
self.targetstr = targetstr
104
self.targetMatch = targetMatch
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)
114
visitAssName = visitName
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:
124
self.visit(node.code)
127
def visitFrom(self, node):
128
for elem in node.modname.split("."):
129
self.popWordsUpTo(elem)
131
for name, alias in node.names:
132
if name == self.targetstr:
133
if alias is not None:
134
pretendNode = Name(alias)
136
pretendNode = Name(name)
137
if findDefinitionFromASTNode(self.scope, pretendNode) \
139
self.appendMatch(name)
140
self.popWordsUpTo(name)
141
if alias is not None:
142
self.popWordsUpTo(alias)
145
def visitGetattr(self, node):
146
for c in node.getChildNodes():
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)
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)
167
def createGetattr(self,fqn):
169
for name in fqn.split(".")[1:]:
170
node = Getattr(node,name)
173
def generateRefsToAttribute(classobj,attrname):
174
rootClasses = getRootClassesOfHierarchy(classobj)
175
attrRefFinder = AttrbuteRefFinder(rootClasses,attrname)
176
for ref in globalScanForMatches(classobj.filename, attrRefFinder, attrname):
178
print >>log.progress,"Done"
181
class AttrbuteRefFinder(MatchFinder):
182
def __init__(self,rootClasses,targetAttribute):
183
self.rootClasses = rootClasses
184
self.targetAttributeName = targetAttribute
187
def visitGetattr(self, node):
188
for c in node.getChildNodes():
191
if node.attrname == self.targetAttributeName:
192
exprtype = getTypeOfExpr(self.scope,node.expr)
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)
201
pass # definately not a match
202
self.popWordsUpTo(node.attrname)
204
visitAssAttr = visitGetattr
206
def visitFunction(self,node): # visit methods
207
if node.name == self.targetAttributeName:
208
parentScope = self.scope.getParent()
210
#print self.targetClasses
211
if isinstance(parentScope,Class) and \
212
self._isAClassInTheSameHierarchy(parentScope):
213
self.appendMatch(node.name)
215
for c in node.getChildNodes():
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: