src/eric7/Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheckerDialog.py

branch
eric7
changeset 10304
ff7d3d6b952d
parent 10302
8cb0dabf852f
child 10341
3fdffd9cc21d
--- a/src/eric7/Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheckerDialog.py	Sat Nov 11 12:44:51 2023 +0100
+++ b/src/eric7/Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheckerDialog.py	Sat Nov 11 16:21:15 2023 +0100
@@ -73,6 +73,7 @@
         self.__fileList = []
         self.__project = None
         self.__arguments = ()
+        self.__statistics = self.__defaultStatistics()
         self.filterFrame.setVisible(False)
 
         self.checkProgress.setVisible(False)
@@ -94,6 +95,65 @@
             self.resultList.sortColumn(), self.resultList.header().sortIndicatorOrder()
         )
 
+    def __defaultStatistics(self):
+        """
+        Private method to return the default statistics entry.
+
+        @return dictionary with default statistics entry
+        @rtype dict
+        """
+        return {
+            "files_checked": 0,
+            "files_issues": 0,
+            "errors": 0,
+            "py_warnings": 0,
+            "warnings": 0,
+        }
+
+    def __updateStatistics(self, fileStatistics):
+        """
+        Private method to update the statistics.
+
+        @param fileStatistics dictionary containing the file statistics
+        @type dict
+        """
+        self.__statistics["files_checked"] += 1
+        if any(fileStatistics.values()):
+            self.__statistics["files_issues"] += 1
+        self.__statistics["errors"] += fileStatistics["errors"]
+        self.__statistics["py_warnings"] += fileStatistics["py_warnings"]
+        self.__statistics["warnings"] += fileStatistics["warnings"]
+
+    def __resetStatistics(self, skipped):
+        """
+        Private method to reset the statistics data.
+
+        @param skipped number of files not being checked
+        @type int
+        """
+        self.__statistics["files_checked"] = 0
+        self.__statistics["files_skipped"] = skipped
+        self.__statistics["files_issues"] = 0
+        self.__statistics["errors"] = 0
+        self.__statistics["py_warnings"] = 0
+        self.__statistics["warnings"] = 0
+
+    def __createFileStatistics(self, problems):
+        """
+        Private method to return the file statistics entry.
+
+        @param problems dictionary with the keys 'error', 'py_warnings' and
+            'warnings' which hold a list of issues each
+        @type dict
+        @return dictionary with the file statistics
+        @rtype dict
+        """
+        return {
+            "errors": 1 if problems.get("error") else 0,
+            "py_warnings": len(problems.get("py_warnings", [])),
+            "warnings": len(problems.get("warnings", [])),
+        }
+
     def __createErrorItem(self, filename, message):
         """
         Private slot to create a new error item in the result list.
@@ -114,6 +174,42 @@
             itm.setForeground(0, Qt.GlobalColor.red)
             itm.setFirstColumnSpanned(True)
 
+    def __createHeaderItem(self, filename, fileStatistics=None):
+        """
+        Private method to create a header item in the result list.
+
+        @param filename file name of file
+        @type str
+        @param fileStatistics dictionary containing statistical data of the check
+            result (defaults to None)
+        @type dict (optional)
+        """
+        itemText = self.__project.getRelativePath(filename)
+
+        if fileStatistics:
+            statisticsTextList = []
+            if fileStatistics["errors"]:
+                statisticsTextList.append(
+                    self.tr("Errors: {0}").format(fileStatistics["errors"])
+                )
+            if fileStatistics["py_warnings"]:
+                statisticsTextList.append(
+                    self.tr("Python Warnings: {0}").format(
+                        fileStatistics["py_warnings"]
+                    )
+                )
+            if fileStatistics["warnings"]:
+                statisticsTextList.append(
+                    self.tr("Warnings: {0}").format(fileStatistics["warnings"])
+                )
+            if statisticsTextList:
+                itemText += "{0}\n{1}".format(itemText, ", ".join(statisticsTextList))
+
+        self.__lastFileItem = QTreeWidgetItem(self.resultList, [itemText])
+        self.__lastFileItem.setFirstColumnSpanned(True)
+        self.__lastFileItem.setExpanded(True)
+        self.__lastFileItem.setData(0, self.filenameRole, filename)
+
     def __createResultItem(
         self, filename, line, index, error, sourcecode, isWarning=False
     ):
@@ -138,12 +234,7 @@
             or self.__lastFileItem.data(0, self.filenameRole) != filename
         ):
             # It's a new file
-            self.__lastFileItem = QTreeWidgetItem(
-                self.resultList, [self.__project.getRelativePath(filename)]
-            )
-            self.__lastFileItem.setFirstColumnSpanned(True)
-            self.__lastFileItem.setExpanded(True)
-            self.__lastFileItem.setData(0, self.filenameRole, filename)
+            self.__createHeaderItem(filename)
 
         itm = QTreeWidgetItem(self.__lastFileItem)
         if isWarning:
@@ -236,7 +327,7 @@
 
             self.on_startButton_clicked()  # press the start button
 
-    def start(self, fn, codestring=""):
+    def start(self, fn, codestring="", skipped=0):
         """
         Public slot to start the syntax check.
 
@@ -245,6 +336,8 @@
         @param codestring string containing the code to be checked. If this is given,
             fn must be a single file name.
         @type str
+        @param skipped number of files not being checked
+        @type int
         """
         self.__batch = False
 
@@ -279,6 +372,7 @@
 
             self.__errorItem = None
             self.__clearErrors(self.files)
+            self.__resetStatistics(skipped)
 
             if codestring or len(self.files) > 0:
                 self.checkProgress.setMaximum(max(1, len(self.files)))
@@ -412,10 +506,10 @@
 
         @param fn filename of the checked file
         @type str
-        @param problems dictionary with the keys 'error' and 'warnings' which
-            hold a list containing details about the error/ warnings
-            (file name, line number, column, codestring (only at syntax
-            errors), the message)
+        @param problems dictionary with the keys 'error', 'py_warnings' and
+            'warnings' which hold a list containing details about the error or
+            warnings (file name, line number, column, codestring (only at syntax
+            errors), message)
         @type dict
         """
         if self.__finished:
@@ -426,33 +520,38 @@
         if not self.__batch and fn != self.filename:
             return
 
-        error = problems.get("error")
-        if error:
-            self.noResults = False
-            _fn, lineno, col, code, msg = error
-            self.__createResultItem(_fn, lineno, col, msg, code, False)
+        fileStatistics = self.__createFileStatistics(problems)
+        self.__updateStatistics(fileStatistics)
+        if any(fileStatistics.values()):
+            self.__createHeaderItem(fn, fileStatistics)
+
+            error = problems.get("error")
+            if error:
+                self.noResults = False
+                filename, lineno, col, code, msg = error
+                self.__createResultItem(filename, lineno, col, msg, code, False)
 
-        warnings = problems.get("py_warnings", []) + problems.get("warnings", [])
-        if warnings:
-            if self.__batch:
-                try:
-                    source = Utilities.readEncodedFile(fn)[0]
-                    source = Utilities.normalizeCode(source)
-                    source = source.splitlines()
-                except (OSError, UnicodeError):
-                    source = ""
-            else:
-                source = self.source.splitlines()
-            for filename, lineno, col, _code, msg in warnings:
-                self.noResults = False
-                if source:
+            warnings = problems.get("py_warnings", []) + problems.get("warnings", [])
+            if warnings:
+                if self.__batch:
                     try:
-                        src_line = source[lineno - 1].strip()
-                    except IndexError:
+                        source = Utilities.readEncodedFile(fn)[0]
+                        source = Utilities.normalizeCode(source)
+                        source = source.splitlines()
+                    except (OSError, UnicodeError):
+                        source = ""
+                else:
+                    source = self.source.splitlines()
+                for filename, lineno, col, _code, msg in warnings:
+                    self.noResults = False
+                    if source:
+                        try:
+                            src_line = source[lineno - 1].strip()
+                        except IndexError:
+                            src_line = ""
+                    else:
                         src_line = ""
-                else:
-                    src_line = ""
-                self.__createResultItem(filename, lineno, col, msg, src_line, True)
+                    self.__createResultItem(filename, lineno, col, msg, src_line, True)
 
         self.progress += 1
         self.checkProgress.setValue(self.progress)
@@ -464,6 +563,20 @@
         if not self.__batch:
             self.check()
 
+    def __updateStatisticsArea(self):
+        """
+        Private method to update the statistics area of the dialog.
+        """
+        self.totalLabel.setText(
+            str(self.__statistics["files_skipped"] + self.__statistics["files_checked"])
+        )
+        self.skippedLabel.setText(str(self.__statistics["files_skipped"]))
+        self.checkedLabel.setText(str(self.__statistics["files_checked"]))
+        self.issuesLabel.setText(str(self.__statistics["files_issues"]))
+        self.errorsLabel.setText(str(self.__statistics["errors"]))
+        self.warningsLabel.setText(str(self.__statistics["warnings"]))
+        self.pyWarningsLabel.setText(str(self.__statistics["py_warnings"]))
+
     def __finish(self):
         """
         Private slot called when the syntax check finished or the user
@@ -493,6 +606,7 @@
                 QHeaderView.ResizeMode.ResizeToContents
             )
             self.resultList.header().setStretchLastSection(True)
+            self.__updateStatisticsArea()
 
             self.checkProgress.setVisible(False)
 
@@ -535,6 +649,7 @@
         Private slot to start a syntax check run.
         """
         fileList = self.__fileList[:]
+        totalLen = len(fileList)
 
         filterString = self.excludeFilesEdit.text()
         self.__data["ExcludeFiles"] = filterString
@@ -550,7 +665,7 @@
         self.noResults = True
         self.cancelled = False
         self.setArguments((self.__data["AdditionalBuiltins"].split(),))
-        self.start(fileList)
+        self.start(fileList, skipped=totalLen - len(fileList))
 
     @pyqtSlot(QTreeWidgetItem, int)
     def on_resultList_itemActivated(self, itm, col):

eric ide

mercurial