src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Complexity/ComplexityChecker.py

branch
eric7
changeset 11150
73d80859079c
parent 11147
dee6e106b4d3
diff -r fc45672fae42 -r 73d80859079c src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Complexity/ComplexityChecker.py
--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Complexity/ComplexityChecker.py	Thu Feb 27 09:22:15 2025 +0100
+++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Complexity/ComplexityChecker.py	Thu Feb 27 14:42:39 2025 +0100
@@ -8,12 +8,13 @@
 """
 
 import ast
-import copy
+
+from CodeStyleTopicChecker import CodeStyleTopicChecker
 
 from .mccabe import PathGraphingAstVisitor
 
 
-class ComplexityChecker:
+class ComplexityChecker(CodeStyleTopicChecker):
     """
     Class implementing a checker for code complexity.
     """
@@ -23,6 +24,7 @@
         "C-111",
         "C-112",
     ]
+    Category = "C"
 
     def __init__(self, source, filename, tree, select, ignore, args):
         """
@@ -41,12 +43,17 @@
         @param args dictionary of arguments for the miscellaneous checks
         @type dict
         """
-        self.__filename = filename
-        self.__source = source[:]
-        self.__tree = copy.deepcopy(tree)
-        self.__select = tuple(select)
-        self.__ignore = tuple(ignore)
-        self.__args = args
+        super().__init__(
+            ComplexityChecker.Category,
+            source,
+            filename,
+            tree,
+            select,
+            ignore,
+            [],
+            True,
+            args,
+        )
 
         self.__defaultArgs = {
             "McCabeComplexity": 10,
@@ -54,82 +61,11 @@
             "LineComplexityScore": 10,
         }
 
-        # statistics counters
-        self.counters = {}
-
-        # collection of detected errors
-        self.errors = []
-
         checkersWithCodes = [
             (self.__checkMcCabeComplexity, ("C-101",)),
             (self.__checkLineComplexity, ("C-111", "C-112")),
         ]
-
-        self.__checkers = []
-        for checker, codes in checkersWithCodes:
-            if any(not (code and self.__ignoreCode(code)) for code in codes):
-                self.__checkers.append(checker)
-
-    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 in self.__ignore or (
-            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
-
-        if code in self.counters:
-            self.counters[code] += 1
-        else:
-            self.counters[code] = 1
-
-        if code:
-            # record the issue with one based line number
-            self.errors.append(
-                {
-                    "file": self.__filename,
-                    "line": lineNumber,
-                    "offset": offset,
-                    "code": code,
-                    "args": args,
-                }
-            )
-
-    def run(self):
-        """
-        Public method to check the given source for code complexity.
-        """
-        if not self.__filename or not self.__source:
-            # don't do anything, if essential data is missing
-            return
-
-        if not self.__checkers:
-            # don't do anything, if no codes were selected
-            return
-
-        for check in self.__checkers:
-            check()
+        self._initializeCheckers(checkersWithCodes)
 
     def __checkMcCabeComplexity(self):
         """
@@ -138,13 +74,13 @@
         try:
             # create the AST again because it is modified by the checker
             tree = compile(
-                "".join(self.__source), self.__filename, "exec", ast.PyCF_ONLY_AST
+                "".join(self.source), self.filename, "exec", ast.PyCF_ONLY_AST
             )
         except (SyntaxError, TypeError):
             # compile errors are already reported by the run() method
             return
 
-        maxComplexity = self.__args.get(
+        maxComplexity = self.args.get(
             "McCabeComplexity", self.__defaultArgs["McCabeComplexity"]
         )
 
@@ -152,7 +88,9 @@
         visitor.preorder(tree, visitor)
         for graph in visitor.graphs.values():
             if graph.complexity() > maxComplexity:
-                self.__error(graph.lineno, 0, "C-101", graph.entity, graph.complexity())
+                self.addError(
+                    graph.lineno + 1, 0, "C-101", graph.entity, graph.complexity()
+                )
 
     def __checkLineComplexity(self):
         """
@@ -162,25 +100,25 @@
         Complexity is defined as the number of AST nodes produced by a line
         of code.
         """
-        maxLineComplexity = self.__args.get(
+        maxLineComplexity = self.args.get(
             "LineComplexity", self.__defaultArgs["LineComplexity"]
         )
-        maxLineComplexityScore = self.__args.get(
+        maxLineComplexityScore = self.args.get(
             "LineComplexityScore", self.__defaultArgs["LineComplexityScore"]
         )
 
         visitor = LineComplexityVisitor()
-        visitor.visit(self.__tree)
+        visitor.visit(self.tree)
 
         sortedItems = visitor.sortedList()
         score = visitor.score()
 
         for line, complexity in sortedItems:
             if complexity > maxLineComplexity:
-                self.__error(line, 0, "C-111", complexity)
+                self.addError(line + 1, 0, "C-111", complexity)
 
         if score > maxLineComplexityScore:
-            self.__error(0, 0, "C-112", score)
+            self.addError(1, 0, "C-112", score)
 
 
 class LineComplexityVisitor(ast.NodeVisitor):
@@ -206,6 +144,7 @@
         """
         if hasattr(node, "lineno"):
             self.__count[node.lineno] = self.__count.get(node.lineno, 0) + 1
+
         self.generic_visit(node)
 
     def sortedList(self):

eric ide

mercurial