Warn about duplicate argument names. Python raises a SyntaxError, but it's not

raised during the actual parsing, but in pass 2 (before bytecode compilation).

Closes #123233

authorTorsten Marek <tmarek@google.com>
changeset99877884076d
branchdefault
phasepublic
hiddenno
parent revision#793ba3ce9abb Unify handling for dangerous default values and make sure that set, dict and list literals
child revision#7080486d663c Improve the warning message for E1124[redundant-keyword-arg].
files modified by this revision
ChangeLog
checkers/base.py
test/input/func_e0108.py
test/messages/func_e0108.txt
# HG changeset patch
# User Torsten Marek <tmarek@google.com>
# Date 1364575962 -3600
# Fri Mar 29 17:52:42 2013 +0100
# Node ID 99877884076d06ab1b9631a04aa810830e07b5b1
# Parent 793ba3ce9abb597bdf440ab2b8f4c279591cd0a9
Warn about duplicate argument names. Python raises a SyntaxError, but it's not
raised during the actual parsing, but in pass 2 (before bytecode compilation).

Closes #123233

diff --git a/ChangeLog b/ChangeLog
@@ -3,19 +3,23 @@
1 
2  --
3      * #74013: new E1310[bad-str-strip-call] message warning when a call to a
4        {l,r,}strip method contains duplicate characters (patch by Torsten Marek)
5 
6 +    * #123233: new E0108[duplicate-argument-name] message reporting duplicate
7 +      argument names
8 +
9      * #124660: internal dependencies should not appear in external dependencies
10        report
11 
12      * #124662: fix name error causing crash when symbols are included in output
13        messages
14 
15      * Simplify checks for dangerous default values by unifying tests
16        for all different mutable compound literals.
17 
18 +
19  2013-02-26 -- 0.27.0
20 
21      * #20693: replace pylint.el by Ian Eure version (patch by J.Kotta)
22 
23      * #105327: add support for --disable=all option and deprecate the
diff --git a/checkers/base.py b/checkers/base.py
@@ -158,20 +158,24 @@
24                '"yield" statements).'),
25      'E0107': ("Use of the non-existent %s operator",
26                'nonexistent-operator',
27                "Used when you attempt to use the C-style pre-increment or"
28                "pre-decrement operator -- and ++, which doesn't exist in Python."),
29 +    'E0108': ('Duplicate argument name %s in function definition',
30 +              'duplicate-argument-name',
31 +              'Duplicate argument names in function definitions are syntax'
32 +              ' errors.'),
33      }
34 
35      def __init__(self, linter):
36          _BasicChecker.__init__(self, linter)
37 
38      @check_messages('E0102')
39      def visit_class(self, node):
40          self._check_redefinition('class', node)
41 
42 -    @check_messages('E0100', 'E0101', 'E0102', 'E0106')
43 +    @check_messages('E0100', 'E0101', 'E0102', 'E0106', 'E0108')
44      def visit_function(self, node):
45          if not redefined_by_decorator(node):
46              self._check_redefinition(node.is_method() and 'method' or 'function', node)
47          # checks for max returns, branch, return in __init__
48          returns = node.nodes_of_class(astng.Return,
@@ -190,10 +194,17 @@
49              for retnode in returns:
50                  if isinstance(retnode.value, astng.Const) and \
51                         retnode.value.value is not None:
52                      self.add_message('E0106', node=node,
53                                       line=retnode.fromlineno)
54 +        args = set()
55 +        for name in node.argnames():
56 +            if name in args:
57 +                self.add_message('E0108', node=node, args=(name,))
58 +            else:
59 +                args.add(name)
60 +
61 
62      @check_messages('E0104')
63      def visit_return(self, node):
64          if not isinstance(node.frame(), astng.Function):
65              self.add_message('E0104', node=node)
diff --git a/test/input/func_e0108.py b/test/input/func_e0108.py
@@ -0,0 +1,14 @@
66 +"""Check for duplicate function arguments."""
67 +__revision__ = 1
68 +
69 +def foo1(_, _):
70 +    """Function with duplicate argument name."""
71 +    pass
72 +
73 +def foo2(_, *_):
74 +    """Function with duplicate argument name."""
75 +    pass
76 +
77 +def foo3(_, _=3):
78 +    """Function with duplicate argument name."""
79 +    pass
diff --git a/test/messages/func_e0108.txt b/test/messages/func_e0108.txt
@@ -0,0 +1,3 @@
80 +E:  4:foo1: Duplicate argument name _ in function definition
81 +E:  8:foo2: Duplicate argument name _ in function definition
82 +E: 12:foo3: Duplicate argument name _ in function definition