Plugins/CheckerPlugins/SyntaxChecker/pyflakes/checker.py

changeset 4502
76f2b46437a6
parent 4465
2fbb5bdb8ddf
child 4555
861e1741985c
equal deleted inserted replaced
4501:3224f20d8eb0 4502:76f2b46437a6
453 node, value.name, existing.source) 453 node, value.name, existing.source)
454 454
455 elif isinstance(existing, Importation) and value.redefines(existing): 455 elif isinstance(existing, Importation) and value.redefines(existing):
456 existing.redefined.append(node) 456 existing.redefined.append(node)
457 457
458 if value.name in self.scope:
459 # then assume the rebound name is used as a global or within a loop
460 value.used = self.scope[value.name].used
461
458 self.scope[value.name] = value 462 self.scope[value.name] = value
459 463
460 def getNodeHandler(self, node_class): 464 def getNodeHandler(self, node_class):
461 try: 465 try:
462 return self._nodeHandlers[node_class] 466 return self._nodeHandlers[node_class]
476 pass 480 pass
477 else: 481 else:
478 return 482 return
479 483
480 scopes = [scope for scope in self.scopeStack[:-1] 484 scopes = [scope for scope in self.scopeStack[:-1]
481 if isinstance(scope, (FunctionScope, ModuleScope))] 485 if isinstance(scope, (FunctionScope, ModuleScope, GeneratorScope))]
482 if isinstance(self.scope, GeneratorScope) and scopes[-1] != self.scopeStack[-2]: 486 if isinstance(self.scope, GeneratorScope) and scopes[-1] != self.scopeStack[-2]:
483 scopes.append(self.scopeStack[-2]) 487 scopes.append(self.scopeStack[-2])
484 488
485 # try enclosing function scopes and global scope 489 # try enclosing function scopes and global scope
486 importStarred = self.scope.importStarred 490 importStarred = self.scope.importStarred
531 binding = Binding(name, node) 535 binding = Binding(name, node)
532 elif name == '__all__' and isinstance(self.scope, ModuleScope): 536 elif name == '__all__' and isinstance(self.scope, ModuleScope):
533 binding = ExportBinding(name, node.parent, self.scope) 537 binding = ExportBinding(name, node.parent, self.scope)
534 else: 538 else:
535 binding = Assignment(name, node) 539 binding = Assignment(name, node)
536 if name in self.scope:
537 binding.used = self.scope[name].used
538 self.addBinding(node, binding) 540 self.addBinding(node, binding)
539 541
540 def handleNodeDelete(self, node): 542 def handleNodeDelete(self, node):
543
544 def on_conditional_branch():
545 """
546 Return `True` if node is part of a conditional body.
547 """
548 current = getattr(node, 'parent', None)
549 while current:
550 if isinstance(current, (ast.If, ast.While, ast.IfExp)):
551 return True
552 current = getattr(current, 'parent', None)
553 return False
554
541 name = getNodeName(node) 555 name = getNodeName(node)
542 if not name: 556 if not name:
543 return 557 return
558
559 if on_conditional_branch():
560 # We can not predict if this conditional branch is going to
561 # be executed.
562 return
563
544 if isinstance(self.scope, FunctionScope) and name in self.scope.globals: 564 if isinstance(self.scope, FunctionScope) and name in self.scope.globals:
545 self.scope.globals.remove(name) 565 self.scope.globals.remove(name)
546 else: 566 else:
547 try: 567 try:
548 del self.scope[name] 568 del self.scope[name]
636 def ignore(self, node): 656 def ignore(self, node):
637 pass 657 pass
638 658
639 # "stmt" type nodes 659 # "stmt" type nodes
640 DELETE = PRINT = FOR = ASYNCFOR = WHILE = IF = WITH = WITHITEM = \ 660 DELETE = PRINT = FOR = ASYNCFOR = WHILE = IF = WITH = WITHITEM = \
641 ASYNCWITH = RAISE = TRYFINALLY = ASSERT = EXEC = EXPR = \ 661 ASYNCWITH = ASYNCWITHITEM = RAISE = TRYFINALLY = ASSERT = EXEC = \
642 ASSIGN = handleChildren 662 EXPR = ASSIGN = handleChildren
643 663
644 CONTINUE = BREAK = PASS = ignore 664 CONTINUE = BREAK = PASS = ignore
645 665
646 # "expr" type nodes 666 # "expr" type nodes
647 BOOLOP = BINOP = UNARYOP = IFEXP = DICT = SET = \ 667 BOOLOP = BINOP = UNARYOP = IFEXP = DICT = SET = \
660 AND = OR = ADD = SUB = MULT = DIV = MOD = POW = LSHIFT = RSHIFT = \ 680 AND = OR = ADD = SUB = MULT = DIV = MOD = POW = LSHIFT = RSHIFT = \
661 BITOR = BITXOR = BITAND = FLOORDIV = INVERT = NOT = UADD = USUB = \ 681 BITOR = BITXOR = BITAND = FLOORDIV = INVERT = NOT = UADD = USUB = \
662 EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = ignore 682 EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = ignore
663 683
664 # additional node types 684 # additional node types
665 LISTCOMP = COMPREHENSION = KEYWORD = handleChildren 685 COMPREHENSION = KEYWORD = handleChildren
666 686
667 def GLOBAL(self, node): 687 def GLOBAL(self, node):
668 """ 688 """
669 Keep track of globals declarations. 689 Keep track of globals declarations.
670 """ 690 """
671 if isinstance(self.scope, FunctionScope): 691 # In doctests, the global scope is an anonymous function at index 1.
672 self.scope.globals.update(node.names) 692 global_scope_index = 0#1 if self.withDoctest else 0
693 global_scope = self.scopeStack[global_scope_index]
694
695 # Ignore 'global' statement in global scope.
696 if self.scope is not global_scope:
697
698 # One 'global' statement can bind multiple (comma-delimited) names.
699 for node_name in node.names:
700 node_value = Assignment(node_name, node)
701
702 # Remove UndefinedName messages already reported for this name.
703 self.messages = [
704 m for m in self.messages if not
705 isinstance(m, messages.UndefinedName) and not
706 m.message_args[0] == node_name]
707
708 # Bind name to global scope if it doesn't exist already.
709 global_scope.setdefault(node_name, node_value)
710
711 # Bind name to non-global scopes, but as already "used".
712 node_value.used = (global_scope, node)
713 for scope in self.scopeStack[global_scope_index + 1:]:
714 scope[node_name] = node_value
715 if isinstance(scope, FunctionScope):
716 scope.globals.add(node_name)
673 717
674 NONLOCAL = GLOBAL 718 NONLOCAL = GLOBAL
675 719
676 def GENERATOREXP(self, node): 720 def GENERATOREXP(self, node):
677 self.pushScope(GeneratorScope) 721 self.pushScope(GeneratorScope)
678 self.handleChildren(node) 722 self.handleChildren(node)
679 self.popScope() 723 self.popScope()
724
725 LISTCOMP = handleChildren if PY2 else GENERATOREXP
680 726
681 DICTCOMP = SETCOMP = GENERATOREXP 727 DICTCOMP = SETCOMP = GENERATOREXP
682 728
683 def NAME(self, node): 729 def NAME(self, node):
684 """ 730 """
699 # must be a Param context -- this only happens for names in function 745 # must be a Param context -- this only happens for names in function
700 # arguments, but these aren't dispatched through here 746 # arguments, but these aren't dispatched through here
701 raise RuntimeError("Got impossible expression context: %r" % (node.ctx,)) 747 raise RuntimeError("Got impossible expression context: %r" % (node.ctx,))
702 748
703 def RETURN(self, node): 749 def RETURN(self, node):
750 if isinstance(self.scope, ClassScope):
751 self.report(messages.ReturnOutsideFunction, node)
752 return
753
704 if ( 754 if (
705 node.value and 755 node.value and
706 hasattr(self.scope, 'returnValue') and 756 hasattr(self.scope, 'returnValue') and
707 not self.scope.returnValue 757 not self.scope.returnValue
708 ): 758 ):
711 761
712 def YIELD(self, node): 762 def YIELD(self, node):
713 self.scope.isGenerator = True 763 self.scope.isGenerator = True
714 self.handleNode(node.value, node) 764 self.handleNode(node.value, node)
715 765
716 YIELDFROM = YIELD 766 AWAIT = YIELDFROM = YIELD
717 767
718 def FUNCTIONDEF(self, node): 768 def FUNCTIONDEF(self, node):
719 for deco in node.decorator_list: 769 for deco in node.decorator_list:
720 self.handleNode(deco, node) 770 self.handleNode(deco, node)
721 self.LAMBDA(node) 771 self.LAMBDA(node)

eric ide

mercurial