--- 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):