277 if node: |
277 if node: |
278 node.parent = parent |
278 node.parent = parent |
279 if self.traceTree: |
279 if self.traceTree: |
280 print(' ' * self.nodeDepth + node.__class__.__name__) |
280 print(' ' * self.nodeDepth + node.__class__.__name__) |
281 self.nodeDepth += 1 |
281 self.nodeDepth += 1 |
282 if self.futuresAllowed and not \ |
282 if self.futuresAllowed and \ |
283 (isinstance(node, ast.ImportFrom) or self.isDocstring(node)): |
283 not (isinstance(node, ast.ImportFrom) or |
|
284 self.isDocstring(node)): |
284 self.futuresAllowed = False |
285 self.futuresAllowed = False |
285 nodeType = node.__class__.__name__.upper() |
286 nodeType = node.__class__.__name__.upper() |
286 try: |
287 try: |
287 handler = getattr(self, nodeType) |
288 handler = getattr(self, nodeType) |
288 handler(node) |
289 handler(node) |
320 |
321 |
321 def addBinding(self, lineno, value, reportRedef=True): |
322 def addBinding(self, lineno, value, reportRedef=True): |
322 ''' |
323 ''' |
323 Called when a binding is altered. |
324 Called when a binding is altered. |
324 |
325 |
325 @param lineno line of the statement responsible for the change (integer) |
326 @param lineno line of the statement responsible for the change |
|
327 (integer) |
326 @param value the optional new value, a Binding instance, associated |
328 @param value the optional new value, a Binding instance, associated |
327 with the binding; if None, the binding is deleted if it exists |
329 with the binding; if None, the binding is deleted if it exists |
328 @param reportRedef flag indicating if rebinding while unused will be |
330 @param reportRedef flag indicating if rebinding while unused will be |
329 reported (boolean) |
331 reported (boolean) |
330 ''' |
332 ''' |
331 if (isinstance(self.scope.get(value.name), FunctionDefinition) |
333 if (isinstance(self.scope.get(value.name), FunctionDefinition) |
332 and isinstance(value, FunctionDefinition) |
334 and isinstance(value, FunctionDefinition) |
333 and not self.scope.get(value.name).is_property |
335 and not self.scope.get(value.name).is_property |
334 and not value.is_property): |
336 and not value.is_property): |
335 self.report(messages.RedefinedFunction, |
337 self.report(messages.RedefinedFunction, |
336 lineno, value.name, self.scope[value.name].source.lineno) |
338 lineno, value.name, |
|
339 self.scope[value.name].source.lineno) |
337 |
340 |
338 if not isinstance(self.scope, ClassScope): |
341 if not isinstance(self.scope, ClassScope): |
339 for scope in self.scopeStack[::-1]: |
342 for scope in self.scopeStack[::-1]: |
340 existing = scope.get(value.name) |
343 existing = scope.get(value.name) |
341 if isinstance(existing, Importation) and \ |
344 if isinstance(existing, Importation) and \ |
343 not isinstance(value, UnBinding) and \ |
346 not isinstance(value, UnBinding) and \ |
344 (not isinstance(value, Importation) or \ |
347 (not isinstance(value, Importation) or \ |
345 value.fullName == existing.fullName) and \ |
348 value.fullName == existing.fullName) and \ |
346 reportRedef: |
349 reportRedef: |
347 self.report(messages.RedefinedWhileUnused, |
350 self.report(messages.RedefinedWhileUnused, |
348 lineno, value.name, scope[value.name].source.lineno) |
351 lineno, value.name, |
|
352 scope[value.name].source.lineno) |
349 |
353 |
350 if isinstance(value, UnBinding): |
354 if isinstance(value, UnBinding): |
351 try: |
355 try: |
352 del self.scope[value.name] |
356 del self.scope[value.name] |
353 except KeyError: |
357 except KeyError: |
444 if (os.path.basename(self.filename) == '__init__.py' and |
448 if (os.path.basename(self.filename) == '__init__.py' and |
445 node.id == '__path__'): |
449 node.id == '__path__'): |
446 # the special name __path__ is valid only in packages |
450 # the special name __path__ is valid only in packages |
447 pass |
451 pass |
448 else: |
452 else: |
449 self.report(messages.UndefinedName, node.lineno, node.id) |
453 self.report(messages.UndefinedName, |
|
454 node.lineno, node.id) |
450 elif isinstance(node.ctx, (ast.Store, ast.AugStore)): |
455 elif isinstance(node.ctx, (ast.Store, ast.AugStore)): |
451 # if the name hasn't already been defined in the current scope |
456 # if the name hasn't already been defined in the current scope |
452 if isinstance(self.scope, FunctionScope) and node.id not in self.scope: |
457 if isinstance(self.scope, FunctionScope) and \ |
|
458 node.id not in self.scope: |
453 # for each function or module scope above us |
459 # for each function or module scope above us |
454 for scope in self.scopeStack[:-1]: |
460 for scope in self.scopeStack[:-1]: |
455 if not isinstance(scope, (FunctionScope, ModuleScope)): |
461 if not isinstance(scope, (FunctionScope, ModuleScope)): |
456 continue |
462 continue |
457 # if the name was defined in that scope, and the name has |
463 # if the name was defined in that scope, and the name has |
484 node.id in self.scope.globals: |
490 node.id in self.scope.globals: |
485 del self.scope.globals[node.id] |
491 del self.scope.globals[node.id] |
486 else: |
492 else: |
487 self.addBinding(node.lineno, UnBinding(node.id, node)) |
493 self.addBinding(node.lineno, UnBinding(node.id, node)) |
488 else: |
494 else: |
489 # must be a Param context -- this only happens for names in function |
495 # must be a Param context -- this only happens for names in |
490 # arguments, but these aren't dispatched through here |
496 # function arguments, but these aren't dispatched through here |
491 raise RuntimeError( |
497 raise RuntimeError( |
492 "Got impossible expression context: {0:r}".format(node.ctx,)) |
498 "Got impossible expression context: {0:r}".format(node.ctx,)) |
493 |
499 |
494 def FUNCTIONDEF(self, node): |
500 def FUNCTIONDEF(self, node): |
495 is_property = False |
501 is_property = False |
516 for arg in arglist: |
522 for arg in arglist: |
517 if isinstance(arg.arg, tuple): |
523 if isinstance(arg.arg, tuple): |
518 addArgs(arg.arg) |
524 addArgs(arg.arg) |
519 else: |
525 else: |
520 if arg.arg in args: |
526 if arg.arg in args: |
521 self.report(messages.DuplicateArgument, node.lineno, arg.arg) |
527 self.report(messages.DuplicateArgument, |
|
528 node.lineno, arg.arg) |
522 args.append(arg.arg) |
529 args.append(arg.arg) |
523 |
530 |
524 def checkUnusedAssignments(): |
531 def checkUnusedAssignments(): |
525 """ |
532 """ |
526 Check to see if any assignments have not been used. |
533 Check to see if any assignments have not been used. |
538 if node.args.vararg: |
545 if node.args.vararg: |
539 args.append(node.args.vararg) |
546 args.append(node.args.vararg) |
540 if node.args.kwarg: |
547 if node.args.kwarg: |
541 args.append(node.args.kwarg) |
548 args.append(node.args.kwarg) |
542 for name in args: |
549 for name in args: |
543 self.addBinding(node.lineno, Argument(name, node), reportRedef=False) |
550 self.addBinding(node.lineno, Argument(name, node), |
|
551 reportRedef=False) |
544 if isinstance(node.body, list): |
552 if isinstance(node.body, list): |
545 self.handleBody(node) |
553 self.handleBody(node) |
546 else: |
554 else: |
547 self.handleNode(node.body, node) |
555 self.handleNode(node.body, node) |
548 self.deferAssignment(checkUnusedAssignments) |
556 self.deferAssignment(checkUnusedAssignments) |
626 self.handleNode(node.value, node) |
634 self.handleNode(node.value, node) |
627 for target in node.targets: |
635 for target in node.targets: |
628 self.handleNode(target, node) |
636 self.handleNode(target, node) |
629 |
637 |
630 def AUGASSIGN(self, node): |
638 def AUGASSIGN(self, node): |
631 # AugAssign is awkward: must set the context explicitly and visit twice, |
639 # AugAssign is awkward: must set the context explicitly and |
632 # once with AugLoad context, once with AugStore context |
640 # visit twice, once with AugLoad context, once with AugStore context |
633 node.target.ctx = ast.AugLoad() |
641 node.target.ctx = ast.AugLoad() |
634 self.handleNode(node.target, node) |
642 self.handleNode(node.target, node) |
635 self.handleNode(node.value, node) |
643 self.handleNode(node.value, node) |
636 node.target.ctx = ast.AugStore() |
644 node.target.ctx = ast.AugStore() |
637 self.handleNode(node.target, node) |
645 self.handleNode(node.target, node) |