Plugins/CheckerPlugins/CodeStyleChecker/MiscellaneousChecker.py

changeset 5585
dab20c39f08c
parent 5389
9b1c800daff3
child 5588
6ba512d9f46a
--- a/Plugins/CheckerPlugins/CodeStyleChecker/MiscellaneousChecker.py	Tue Mar 07 18:25:42 2017 +0100
+++ b/Plugins/CheckerPlugins/CodeStyleChecker/MiscellaneousChecker.py	Tue Mar 07 18:42:41 2017 +0100
@@ -22,6 +22,10 @@
         "M101", "M102",
         "M111", "M112",
         "M121",
+        "M131", "M132",
+        
+        "M191", "M192", "M193", "M194",
+        "M195", "M196", "M197", "M198",
         
         "M601",
         "M611", "M612", "M613",
@@ -38,6 +42,12 @@
     
     Formatter = Formatter()
     FormatFieldRegex = re.compile(r'^((?:\s|.)*?)(\..*|\[.*\])?$')
+    
+    BuiltinsWhiteList = [
+        "__name__",
+        "__doc__",
+        "credits",
+    ]
 
     def __init__(self, source, filename, select, ignore, expected, repeat,
                  args):
@@ -71,6 +81,15 @@
             r'(\bexcept:)')                             # __IGNORE_WARNING__
         self.__pep3101FormatRegex = re.compile(
             r'^(?:[^\'"]*[\'"][^\'"]*[\'"])*\s*%|^\s*%')
+        
+        if sys.version_info >= (3, 0):
+            import builtins
+            self.__builtins = [b for b in dir(builtins)
+                               if b not in self.BuiltinsWhiteList]
+        else:
+            import __builtin__
+            self.__builtins = [b for b in dir(__builtin__)
+                               if b not in self.BuiltinsWhiteList]
 
         # statistics counters
         self.counters = {}
@@ -82,6 +101,9 @@
             (self.__checkCoding, ("M101", "M102")),
             (self.__checkCopyright, ("M111", "M112")),
             (self.__checkBlindExcept, ("M121",)),
+            (self.__checkBuiltins, ("M131", "M132")),
+            (self.__checkComprehensions, ("M191", "M192", "M193", "M194",
+                                          "M195", "M196", "M197", "M198")),
             (self.__checkPep3101, ("M601",)),
             (self.__checkFormatString, ("M611", "M612", "M613",
                                         "M621", "M622", "M623", "M624", "M625",
@@ -477,6 +499,71 @@
             return set(), False, False
         else:
             return fields, implicit, explicit
+    
+    def __checkBuiltins(self):
+        """
+        Private method to check, if built-ins are shadowed.
+        """
+        for node in ast.walk(self.__tree):
+            if isinstance(node, ast.Assign):
+                # assign statement
+                for element in node.targets:
+                    if isinstance(element, ast.Name) and \
+                       element.id in self.__builtins:
+                        self.__error(element.lineno - 1, element.col_offset,
+                                     "M131", element.id)
+            elif isinstance(node, ast.FunctionDef):
+                if sys.version_info >= (3, 0):
+                    for arg in node.args.args:
+                        if isinstance(arg, ast.arg) and \
+                           arg.arg in self.__builtins:
+                            self.__error(arg.lineno - 1, arg.col_offset,
+                                         "M132", arg.arg)
+                else:
+                    for arg in node.args.args:
+                        if isinstance(arg, ast.Name) and \
+                           arg.id in self.__builtins:
+                            self.__error(arg.lineno - 1, arg.col_offset,
+                                         "M132", arg.id)
+    
+    def __checkComprehensions(self):
+        """
+        Private method to check some comprehension related things.
+        """
+        for node in ast.walk(self.__tree):
+            if (isinstance(node, ast.Call) and
+               len(node.args) == 1 and
+               isinstance(node.func, ast.Name)):
+                if (isinstance(node.args[0], ast.GeneratorExp) and
+                        node.func.id in ('list', 'set', 'dict')):
+                    errorCode = {
+                        "list": "M191",
+                        "set": "M192",
+                        "dict": "M193",
+                    }[node.func.id]
+                    self.__error(node.lineno - 1, node.col_offset, errorCode)
+
+                elif (isinstance(node.args[0], ast.ListComp) and
+                      node.func.id in ('set', 'dict')):
+                    errorCode = {
+                        'set': 'M194',
+                        'dict': 'M195',
+                    }[node.func.id]
+                    self.__error(node.lineno - 1, node.col_offset, errorCode)
+
+                elif (isinstance(node.args[0], ast.List) and
+                      node.func.id in ('set', 'dict')):
+                    errorCode = {
+                        'set': 'M196',
+                        'dict': 'M197',
+                    }[node.func.id]
+                    self.__error(node.lineno - 1, node.col_offset, errorCode)
+
+                elif (isinstance(node.args[0], ast.ListComp) and
+                      node.func.id in ('all', 'any', 'frozenset', 'max', 'min',
+                                       'sorted', 'sum', 'tuple',)):
+                    self.__error(node.lineno - 1, node.col_offset, "M198",
+                                 node.func.id)
 
 
 class TextVisitor(ast.NodeVisitor):

eric ide

mercurial