src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyChecker.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
diff -r 3fc8dfeb6ebe -r b99e7fd55fd3 src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyChecker.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyChecker.py	Thu Jul 07 11:23:56 2022 +0200
@@ -0,0 +1,148 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2021 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the checker for simplifying Python code.
+"""
+
+import ast
+import copy
+
+from .SimplifyNodeVisitor import SimplifyNodeVisitor
+
+
+class SimplifyChecker:
+    """
+    Class implementing a checker for to help simplifying Python code.
+    """
+    Codes = [
+        # Python-specifics
+        "Y101", "Y102", "Y103", "Y104", "Y105", "Y106", "Y107", "Y108",
+        "Y109", "Y110", "Y111", "Y112", "Y113", "Y114", "Y115", "Y116",
+        "Y117", "Y118", "Y119", "Y120", "Y121", "Y122",
+       
+        # Python-specifics not part of flake8-simplify
+        "Y181", "Y182",
+        
+        # Comparations
+        "Y201", "Y202", "Y203", "Y204", "Y205", "Y206", "Y207", "Y208",
+        "Y211", "Y212", "Y213",
+        "Y221", "Y222", "Y223", "Y224",
+        
+        # Opinionated
+        "Y301",
+        
+        # General Code Style
+        "Y401", "Y402",
+    ]
+    
+    def __init__(self, source, filename, tree, selected, ignored, expected,
+                 repeat):
+        """
+        Constructor
+        
+        @param source source code to be checked
+        @type list of str
+        @param filename name of the source file
+        @type str
+        @param tree AST tree of the source code
+        @type ast.Module
+        @param selected list of selected codes
+        @type list of str
+        @param ignored list of codes to be ignored
+        @type list of str
+        @param expected list of expected codes
+        @type list of str
+        @param repeat flag indicating to report each occurrence of a code
+        @type bool
+        """
+        self.__select = tuple(selected)
+        self.__ignore = ('',) if selected else tuple(ignored)
+        self.__expected = expected[:]
+        self.__repeat = repeat
+        self.__filename = filename
+        self.__source = source[:]
+        self.__tree = copy.deepcopy(tree)
+        
+        # statistics counters
+        self.counters = {}
+        
+        # collection of detected errors
+        self.errors = []
+        
+        self.__checkCodes = (code for code in self.Codes
+                             if not self.__ignoreCode(code))
+    
+    def __ignoreCode(self, code):
+        """
+        Private method to check if the message code should be ignored.
+
+        @param code message code to check for
+        @type str
+        @return flag indicating to ignore the given code
+        @rtype bool
+        """
+        return (code.startswith(self.__ignore) and
+                not code.startswith(self.__select))
+    
+    def __error(self, lineNumber, offset, code, *args):
+        """
+        Private method to record an issue.
+        
+        @param lineNumber line number of the issue
+        @type int
+        @param offset position within line of the issue
+        @type int
+        @param code message code
+        @type str
+        @param args arguments for the message
+        @type list
+        """
+        if self.__ignoreCode(code):
+            return
+        
+        # record the issue with one based line number
+        errorInfo = {
+            "file": self.__filename,
+            "line": lineNumber + 1,
+            "offset": offset,
+            "code": code,
+            "args": args,
+        }
+        
+        if errorInfo not in self.errors:
+            # this issue was not seen before
+            if code in self.counters:
+                self.counters[code] += 1
+            else:
+                self.counters[code] = 1
+            
+            # Don't care about expected codes
+            if code in self.__expected:
+                return
+            
+            if code and (self.counters[code] == 1 or self.__repeat):
+                self.errors.append(errorInfo)
+    
+    def run(self):
+        """
+        Public method to check the given source against functions
+        to be replaced by 'pathlib' equivalents.
+        """
+        if not self.__filename:
+            # don't do anything, if essential data is missing
+            return
+        
+        if not self.__checkCodes:
+            # don't do anything, if no codes were selected
+            return
+        
+        # Add parent information
+        for node in ast.walk(self.__tree):
+            for child in ast.iter_child_nodes(node):
+                child.parent = node  # type: ignore
+        
+        visitor = SimplifyNodeVisitor(self.__error)
+        visitor.visit(self.__tree)

eric ide

mercurial