92 """ |
93 """ |
93 self.resultList.sortItems( |
94 self.resultList.sortItems( |
94 self.resultList.sortColumn(), self.resultList.header().sortIndicatorOrder() |
95 self.resultList.sortColumn(), self.resultList.header().sortIndicatorOrder() |
95 ) |
96 ) |
96 |
97 |
|
98 def __defaultStatistics(self): |
|
99 """ |
|
100 Private method to return the default statistics entry. |
|
101 |
|
102 @return dictionary with default statistics entry |
|
103 @rtype dict |
|
104 """ |
|
105 return { |
|
106 "files_checked": 0, |
|
107 "files_issues": 0, |
|
108 "errors": 0, |
|
109 "py_warnings": 0, |
|
110 "warnings": 0, |
|
111 } |
|
112 |
|
113 def __updateStatistics(self, fileStatistics): |
|
114 """ |
|
115 Private method to update the statistics. |
|
116 |
|
117 @param fileStatistics dictionary containing the file statistics |
|
118 @type dict |
|
119 """ |
|
120 self.__statistics["files_checked"] += 1 |
|
121 if any(fileStatistics.values()): |
|
122 self.__statistics["files_issues"] += 1 |
|
123 self.__statistics["errors"] += fileStatistics["errors"] |
|
124 self.__statistics["py_warnings"] += fileStatistics["py_warnings"] |
|
125 self.__statistics["warnings"] += fileStatistics["warnings"] |
|
126 |
|
127 def __resetStatistics(self, skipped): |
|
128 """ |
|
129 Private method to reset the statistics data. |
|
130 |
|
131 @param skipped number of files not being checked |
|
132 @type int |
|
133 """ |
|
134 self.__statistics["files_checked"] = 0 |
|
135 self.__statistics["files_skipped"] = skipped |
|
136 self.__statistics["files_issues"] = 0 |
|
137 self.__statistics["errors"] = 0 |
|
138 self.__statistics["py_warnings"] = 0 |
|
139 self.__statistics["warnings"] = 0 |
|
140 |
|
141 def __createFileStatistics(self, problems): |
|
142 """ |
|
143 Private method to return the file statistics entry. |
|
144 |
|
145 @param problems dictionary with the keys 'error', 'py_warnings' and |
|
146 'warnings' which hold a list of issues each |
|
147 @type dict |
|
148 @return dictionary with the file statistics |
|
149 @rtype dict |
|
150 """ |
|
151 return { |
|
152 "errors": 1 if problems.get("error") else 0, |
|
153 "py_warnings": len(problems.get("py_warnings", [])), |
|
154 "warnings": len(problems.get("warnings", [])), |
|
155 } |
|
156 |
97 def __createErrorItem(self, filename, message): |
157 def __createErrorItem(self, filename, message): |
98 """ |
158 """ |
99 Private slot to create a new error item in the result list. |
159 Private slot to create a new error item in the result list. |
100 |
160 |
101 @param filename name of the file |
161 @param filename name of the file |
112 if not self.resultList.findItems(msg, Qt.MatchFlag.MatchExactly): |
172 if not self.resultList.findItems(msg, Qt.MatchFlag.MatchExactly): |
113 itm = QTreeWidgetItem(self.__errorItem, [msg]) |
173 itm = QTreeWidgetItem(self.__errorItem, [msg]) |
114 itm.setForeground(0, Qt.GlobalColor.red) |
174 itm.setForeground(0, Qt.GlobalColor.red) |
115 itm.setFirstColumnSpanned(True) |
175 itm.setFirstColumnSpanned(True) |
116 |
176 |
|
177 def __createHeaderItem(self, filename, fileStatistics=None): |
|
178 """ |
|
179 Private method to create a header item in the result list. |
|
180 |
|
181 @param filename file name of file |
|
182 @type str |
|
183 @param fileStatistics dictionary containing statistical data of the check |
|
184 result (defaults to None) |
|
185 @type dict (optional) |
|
186 """ |
|
187 itemText = self.__project.getRelativePath(filename) |
|
188 |
|
189 if fileStatistics: |
|
190 statisticsTextList = [] |
|
191 if fileStatistics["errors"]: |
|
192 statisticsTextList.append( |
|
193 self.tr("Errors: {0}").format(fileStatistics["errors"]) |
|
194 ) |
|
195 if fileStatistics["py_warnings"]: |
|
196 statisticsTextList.append( |
|
197 self.tr("Python Warnings: {0}").format( |
|
198 fileStatistics["py_warnings"] |
|
199 ) |
|
200 ) |
|
201 if fileStatistics["warnings"]: |
|
202 statisticsTextList.append( |
|
203 self.tr("Warnings: {0}").format(fileStatistics["warnings"]) |
|
204 ) |
|
205 if statisticsTextList: |
|
206 itemText += "{0}\n{1}".format(itemText, ", ".join(statisticsTextList)) |
|
207 |
|
208 self.__lastFileItem = QTreeWidgetItem(self.resultList, [itemText]) |
|
209 self.__lastFileItem.setFirstColumnSpanned(True) |
|
210 self.__lastFileItem.setExpanded(True) |
|
211 self.__lastFileItem.setData(0, self.filenameRole, filename) |
|
212 |
117 def __createResultItem( |
213 def __createResultItem( |
118 self, filename, line, index, error, sourcecode, isWarning=False |
214 self, filename, line, index, error, sourcecode, isWarning=False |
119 ): |
215 ): |
120 """ |
216 """ |
121 Private method to create an entry in the result list. |
217 Private method to create an entry in the result list. |
234 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) |
325 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) |
235 self.builtinsEdit.setText(self.__data["AdditionalBuiltins"]) |
326 self.builtinsEdit.setText(self.__data["AdditionalBuiltins"]) |
236 |
327 |
237 self.on_startButton_clicked() # press the start button |
328 self.on_startButton_clicked() # press the start button |
238 |
329 |
239 def start(self, fn, codestring=""): |
330 def start(self, fn, codestring="", skipped=0): |
240 """ |
331 """ |
241 Public slot to start the syntax check. |
332 Public slot to start the syntax check. |
242 |
333 |
243 @param fn file or list of files or directory to be checked |
334 @param fn file or list of files or directory to be checked |
244 @type str or list of str |
335 @type str or list of str |
245 @param codestring string containing the code to be checked. If this is given, |
336 @param codestring string containing the code to be checked. If this is given, |
246 fn must be a single file name. |
337 fn must be a single file name. |
247 @type str |
338 @type str |
|
339 @param skipped number of files not being checked |
|
340 @type int |
248 """ |
341 """ |
249 self.__batch = False |
342 self.__batch = False |
250 |
343 |
251 if self.syntaxCheckService is not None: |
344 if self.syntaxCheckService is not None: |
252 if self.__project is None: |
345 if self.__project is None: |
410 """ |
504 """ |
411 Private slot to display the reported messages. |
505 Private slot to display the reported messages. |
412 |
506 |
413 @param fn filename of the checked file |
507 @param fn filename of the checked file |
414 @type str |
508 @type str |
415 @param problems dictionary with the keys 'error' and 'warnings' which |
509 @param problems dictionary with the keys 'error', 'py_warnings' and |
416 hold a list containing details about the error/ warnings |
510 'warnings' which hold a list containing details about the error or |
417 (file name, line number, column, codestring (only at syntax |
511 warnings (file name, line number, column, codestring (only at syntax |
418 errors), the message) |
512 errors), message) |
419 @type dict |
513 @type dict |
420 """ |
514 """ |
421 if self.__finished: |
515 if self.__finished: |
422 return |
516 return |
423 |
517 |
424 # Check if it's the requested file, otherwise ignore signal if not |
518 # Check if it's the requested file, otherwise ignore signal if not |
425 # in batch mode |
519 # in batch mode |
426 if not self.__batch and fn != self.filename: |
520 if not self.__batch and fn != self.filename: |
427 return |
521 return |
428 |
522 |
429 error = problems.get("error") |
523 fileStatistics = self.__createFileStatistics(problems) |
430 if error: |
524 self.__updateStatistics(fileStatistics) |
431 self.noResults = False |
525 if any(fileStatistics.values()): |
432 _fn, lineno, col, code, msg = error |
526 self.__createHeaderItem(fn, fileStatistics) |
433 self.__createResultItem(_fn, lineno, col, msg, code, False) |
527 |
434 |
528 error = problems.get("error") |
435 warnings = problems.get("py_warnings", []) + problems.get("warnings", []) |
529 if error: |
436 if warnings: |
|
437 if self.__batch: |
|
438 try: |
|
439 source = Utilities.readEncodedFile(fn)[0] |
|
440 source = Utilities.normalizeCode(source) |
|
441 source = source.splitlines() |
|
442 except (OSError, UnicodeError): |
|
443 source = "" |
|
444 else: |
|
445 source = self.source.splitlines() |
|
446 for filename, lineno, col, _code, msg in warnings: |
|
447 self.noResults = False |
530 self.noResults = False |
448 if source: |
531 filename, lineno, col, code, msg = error |
|
532 self.__createResultItem(filename, lineno, col, msg, code, False) |
|
533 |
|
534 warnings = problems.get("py_warnings", []) + problems.get("warnings", []) |
|
535 if warnings: |
|
536 if self.__batch: |
449 try: |
537 try: |
450 src_line = source[lineno - 1].strip() |
538 source = Utilities.readEncodedFile(fn)[0] |
451 except IndexError: |
539 source = Utilities.normalizeCode(source) |
|
540 source = source.splitlines() |
|
541 except (OSError, UnicodeError): |
|
542 source = "" |
|
543 else: |
|
544 source = self.source.splitlines() |
|
545 for filename, lineno, col, _code, msg in warnings: |
|
546 self.noResults = False |
|
547 if source: |
|
548 try: |
|
549 src_line = source[lineno - 1].strip() |
|
550 except IndexError: |
|
551 src_line = "" |
|
552 else: |
452 src_line = "" |
553 src_line = "" |
453 else: |
554 self.__createResultItem(filename, lineno, col, msg, src_line, True) |
454 src_line = "" |
|
455 self.__createResultItem(filename, lineno, col, msg, src_line, True) |
|
456 |
555 |
457 self.progress += 1 |
556 self.progress += 1 |
458 self.checkProgress.setValue(self.progress) |
557 self.checkProgress.setValue(self.progress) |
459 if time.monotonic() - self.__timenow > 0.01: |
558 if time.monotonic() - self.__timenow > 0.01: |
460 QApplication.processEvents() |
559 QApplication.processEvents() |
461 self.__timenow = time.monotonic() |
560 self.__timenow = time.monotonic() |
462 self.__resort() |
561 self.__resort() |
463 |
562 |
464 if not self.__batch: |
563 if not self.__batch: |
465 self.check() |
564 self.check() |
|
565 |
|
566 def __updateStatisticsArea(self): |
|
567 """ |
|
568 Private method to update the statistics area of the dialog. |
|
569 """ |
|
570 self.totalLabel.setText( |
|
571 str(self.__statistics["files_skipped"] + self.__statistics["files_checked"]) |
|
572 ) |
|
573 self.skippedLabel.setText(str(self.__statistics["files_skipped"])) |
|
574 self.checkedLabel.setText(str(self.__statistics["files_checked"])) |
|
575 self.issuesLabel.setText(str(self.__statistics["files_issues"])) |
|
576 self.errorsLabel.setText(str(self.__statistics["errors"])) |
|
577 self.warningsLabel.setText(str(self.__statistics["warnings"])) |
|
578 self.pyWarningsLabel.setText(str(self.__statistics["py_warnings"])) |
466 |
579 |
467 def __finish(self): |
580 def __finish(self): |
468 """ |
581 """ |
469 Private slot called when the syntax check finished or the user |
582 Private slot called when the syntax check finished or the user |
470 pressed the button. |
583 pressed the button. |
548 |
663 |
549 self.resultList.clear() |
664 self.resultList.clear() |
550 self.noResults = True |
665 self.noResults = True |
551 self.cancelled = False |
666 self.cancelled = False |
552 self.setArguments((self.__data["AdditionalBuiltins"].split(),)) |
667 self.setArguments((self.__data["AdditionalBuiltins"].split(),)) |
553 self.start(fileList) |
668 self.start(fileList, skipped=totalLen - len(fileList)) |
554 |
669 |
555 @pyqtSlot(QTreeWidgetItem, int) |
670 @pyqtSlot(QTreeWidgetItem, int) |
556 def on_resultList_itemActivated(self, itm, col): |
671 def on_resultList_itemActivated(self, itm, col): |
557 """ |
672 """ |
558 Private slot to handle the activation of an item. |
673 Private slot to handle the activation of an item. |