src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleTopicChecker.py

branch
eric7
changeset 11150
73d80859079c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleTopicChecker.py	Thu Feb 27 14:42:39 2025 +0100
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2025 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the topic checker base class containing common methods.
+"""
+
+import copy
+
+
+class CodeStyleTopicChecker:
+    """
+    Class implementing the topic checker base class.
+    """
+
+    def __init__(
+        self, category, source, filename, tree, select, ignore, expected, repeat, args
+    ):
+        """
+        Constructor
+
+        @param category checker category code (one to three uppercase characters
+        @type str
+        @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 select list of selected codes
+        @type list of str
+        @param ignore 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
+        @param args dictionary of arguments for the various checks
+        @type dict
+        """
+        self.__category = category
+
+        codeFilter = f"{category}-"
+        self.selected = tuple(x for x in select if x.startswith(codeFilter))
+        self.ignored = tuple(
+            x for x in ignore if x.startswith(codeFilter) or x == category
+        )
+        self.expected = [x for x in expected if x.startswith(codeFilter)]
+
+        self.repeat = repeat
+        self.filename = filename
+        self.source = source[:]
+        self.tree = copy.deepcopy(tree)
+        self.args = args
+
+        # statistics counters
+        self.counters = {}
+
+        # collection of detected errors
+        self.errors = []
+
+    def _initializeCheckers(self, checkersWithCodes):
+        """
+        Protected method to determine the list of check methods to be run.
+
+        This list is determined considering the list if selected and ignored issue
+        codes.
+
+        @param checkersWithCodes DESCRIPTION
+        @type TYPE
+        """
+        # checkers to be run
+        self.__checkers = []
+
+        for checker, msgCodes in checkersWithCodes:
+            if any(not (msgCode and self._ignoreCode(msgCode)) for msgCode in msgCodes):
+                self.__checkers.append(checker)
+
+    def _ignoreCode(self, code):
+        """
+        Protected 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.ignored or (
+            code.startswith(self.ignored) and not code.startswith(self.selected)
+        )
+
+    def addError(self, lineNumber, offset, msgCode, *args):
+        """
+        Public method to record an issue.
+
+        @param lineNumber line number of the issue (one based)
+        @type int
+        @param offset position within line of the issue
+        @type int
+        @param msgCode message code
+        @type str
+        @param args arguments for the message
+        @type list
+        """
+        if self._ignoreCode(msgCode):
+            return
+
+        if msgCode in self.counters:
+            self.counters[msgCode] += 1
+        else:
+            self.counters[msgCode] = 1
+
+        # Don't care about expected codes
+        if msgCode in self.expected:
+            return
+
+        if msgCode and (self.counters[msgCode] == 1 or self.repeat):
+            # record the issue with one based line number
+            self.errors.append(
+                {
+                    "file": self.filename,
+                    "line": lineNumber,
+                    "offset": offset,
+                    "code": msgCode,
+                    "args": args,
+                }
+            )
+
+    def addErrorFromNode(self, node, msgCode, *args):
+        """
+        Public method to record an issue given the faulty ast node.
+
+        @param node reference to the node containing the issue
+        @type ast.AST
+        @param msgCode message code
+        @type str
+        @param args arguments for the message
+        @type list
+        """
+        self.addError(node.lineno, node.col_offset, msgCode, *args)
+
+    def run(self):
+        """
+        Public method to execute the relevant checks.
+        """
+        if not self.filename:
+            # 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()

eric ide

mercurial