Plugins/CheckerPlugins/CodeStyleChecker/mccabe.py

changeset 5620
6bca68319bb4
parent 4555
861e1741985c
equal deleted inserted replaced
5619:ab999dc48132 5620:6bca68319bb4
6 from __future__ import with_statement 6 from __future__ import with_statement
7 7
8 import collections 8 import collections
9 import ast 9 import ast
10 10
11 __version__ = '0.3.1_eric6' 11 __version__ = '0.6.1_eric6'
12 12
13 13
14 class ASTVisitor(object): 14 class ASTVisitor(object):
15 """Performs a depth-first walk of the AST.""" 15 """Performs a depth-first walk of the AST."""
16 16
51 def dot_id(self): 51 def dot_id(self):
52 return id(self) 52 return id(self)
53 53
54 54
55 class PathGraph(object): 55 class PathGraph(object):
56 def __init__(self, name, entity, lineno): 56 def __init__(self, name, entity, lineno, column=0):
57 self.name = name 57 self.name = name
58 self.entity = entity 58 self.entity = entity
59 self.lineno = lineno 59 self.lineno = lineno
60 self.column = column
60 self.nodes = collections.defaultdict(list) 61 self.nodes = collections.defaultdict(list)
61 62
62 def connect(self, n1, n2): 63 def connect(self, n1, n2):
63 self.nodes[n1].append(n2) 64 self.nodes[n1].append(n2)
64 # Ensure that the destination node is always counted. 65 # Ensure that the destination node is always counted.
106 if self.classname: 107 if self.classname:
107 entity = '%s%s' % (self.classname, node.name) 108 entity = '%s%s' % (self.classname, node.name)
108 else: 109 else:
109 entity = node.name 110 entity = node.name
110 111
111 name = '%d:1: %r' % (node.lineno, entity) 112 name = '%d:%d: %r' % (node.lineno, node.col_offset, entity)
112 113
113 if self.graph is not None: 114 if self.graph is not None:
114 # closure 115 # closure
115 pathnode = self.appendPathNode(name) 116 pathnode = self.appendPathNode(name)
116 self.tail = pathnode 117 self.tail = pathnode
118 bottom = PathNode("", look='point') 119 bottom = PathNode("", look='point')
119 self.graph.connect(self.tail, bottom) 120 self.graph.connect(self.tail, bottom)
120 self.graph.connect(pathnode, bottom) 121 self.graph.connect(pathnode, bottom)
121 self.tail = bottom 122 self.tail = bottom
122 else: 123 else:
123 self.graph = PathGraph(name, entity, node.lineno) 124 self.graph = PathGraph(name, entity, node.lineno, node.col_offset)
124 pathnode = PathNode(name) 125 pathnode = PathNode(name)
125 self.tail = pathnode 126 self.tail = pathnode
126 self.dispatch_list(node.body) 127 self.dispatch_list(node.body)
127 self.graphs["%s%s" % (self.classname, node.name)] = self.graph 128 self.graphs["%s%s" % (self.classname, node.name)] = self.graph
128 self.reset() 129 self.reset()
149 else: 150 else:
150 lineno = node.lineno 151 lineno = node.lineno
151 name = "Stmt %d" % lineno 152 name = "Stmt %d" % lineno
152 self.appendPathNode(name) 153 self.appendPathNode(name)
153 154
154 visitAssert = visitAssign = visitAugAssign = visitDelete = visitPrint = \ 155 def default(self, node, *args):
155 visitRaise = visitYield = visitImport = visitCall = visitSubscript = \ 156 if isinstance(node, ast.stmt):
156 visitPass = visitContinue = visitBreak = visitGlobal = visitReturn = \ 157 self.visitSimpleStatement(node)
157 visitSimpleStatement 158 else:
159 super(PathGraphingAstVisitor, self).default(node, *args)
158 160
159 def visitLoop(self, node): 161 def visitLoop(self, node):
160 name = "Loop %d" % node.lineno 162 name = "Loop %d" % node.lineno
161 self._subgraph(node, name) 163 self._subgraph(node, name)
162 164
163 visitFor = visitAsyncFor = visitWhile = visitLoop 165 visitAsyncFor = visitFor = visitWhile = visitLoop
164 166
165 def visitIf(self, node): 167 def visitIf(self, node):
166 name = "If %d" % node.lineno 168 name = "If %d" % node.lineno
167 self._subgraph(node, name) 169 self._subgraph(node, name)
168 170
169 def _subgraph(self, node, name, extra_blocks=()): 171 def _subgraph(self, node, name, extra_blocks=()):
170 """create the subgraphs representing any `if` and `for` statements""" 172 """create the subgraphs representing any `if` and `for` statements"""
171 if self.graph is None: 173 if self.graph is None:
172 # global loop 174 # global loop
173 self.graph = PathGraph(name, name, node.lineno) 175 self.graph = PathGraph(name, name, node.lineno, node.col_offset)
174 pathnode = PathNode(name) 176 pathnode = PathNode(name)
175 self._subgraph_parse(node, pathnode, extra_blocks) 177 self._subgraph_parse(node, pathnode, extra_blocks)
176 self.graphs["%s%s" % (self.classname, name)] = self.graph 178 self.graphs["%s%s" % (self.classname, name)] = self.graph
177 self.reset() 179 self.reset()
178 else: 180 else:
209 211
210 def visitWith(self, node): 212 def visitWith(self, node):
211 name = "With %d" % node.lineno 213 name = "With %d" % node.lineno
212 self.appendPathNode(name) 214 self.appendPathNode(name)
213 self.dispatch_list(node.body) 215 self.dispatch_list(node.body)
214 216
215 visitAsyncWith = visitWith 217 visitAsyncWith = visitWith
216 218
217 # 219 #
218 # eflag: noqa = M702 220 # eflag: noqa = M702

eric ide

mercurial