130 # enabled, ignorecount) |
132 # enabled, ignorecount) |
131 self.bookmarks = [] # bookmarks are just a list of handles to the |
133 self.bookmarks = [] # bookmarks are just a list of handles to the |
132 # bookmark markers |
134 # bookmark markers |
133 self.syntaxerrors = {} # key: marker handle |
135 self.syntaxerrors = {} # key: marker handle |
134 # value: error message |
136 # value: error message |
|
137 self.warnings = {} # key: marker handle |
|
138 # value: warning message |
135 self.notcoveredMarkers = [] # just a list of marker handles |
139 self.notcoveredMarkers = [] # just a list of marker handles |
136 |
140 |
137 self.condHistory = [] |
141 self.condHistory = [] |
138 self.lexer_ = None |
142 self.lexer_ = None |
139 self.__lexerReset = False |
143 self.__lexerReset = False |
906 self.__showSyntaxError) |
910 self.__showSyntaxError) |
907 self.marginMenuActs["ClearSyntaxError"] = \ |
911 self.marginMenuActs["ClearSyntaxError"] = \ |
908 self.indicMarginMenu.addAction(self.trUtf8('Clear syntax error'), |
912 self.indicMarginMenu.addAction(self.trUtf8('Clear syntax error'), |
909 self.clearSyntaxError) |
913 self.clearSyntaxError) |
910 self.indicMarginMenu.addSeparator() |
914 self.indicMarginMenu.addSeparator() |
|
915 self.marginMenuActs["NextWarningMarker"] = \ |
|
916 self.indicMarginMenu.addAction(self.trUtf8("Next warning"), |
|
917 self.nextFlakesWarning) |
|
918 self.marginMenuActs["PreviousWarningMarker"] = \ |
|
919 self.indicMarginMenu.addAction(self.trUtf8("Previous warning"), |
|
920 self.previousFlakesWarning) |
|
921 self.marginMenuActs["ShowWarning"] = \ |
|
922 self.indicMarginMenu.addAction(self.trUtf8('Show warning message'), |
|
923 self.__showFlakesWarning) |
|
924 self.marginMenuActs["ClearWarnings"] = \ |
|
925 self.indicMarginMenu.addAction(self.trUtf8('Clear warnings'), |
|
926 self.clearFlakesWarnings) |
|
927 self.indicMarginMenu.addSeparator() |
911 self.marginMenuActs["NextCoverageMarker"] = \ |
928 self.marginMenuActs["NextCoverageMarker"] = \ |
912 self.indicMarginMenu.addAction(self.trUtf8('Next uncovered line'), |
929 self.indicMarginMenu.addAction(self.trUtf8('Next uncovered line'), |
913 self.nextUncovered) |
930 self.nextUncovered) |
914 self.marginMenuActs["PreviousCoverageMarker"] = \ |
931 self.marginMenuActs["PreviousCoverageMarker"] = \ |
915 self.indicMarginMenu.addAction(self.trUtf8('Previous uncovered line'), |
932 self.indicMarginMenu.addAction(self.trUtf8('Previous uncovered line'), |
950 self.marginMenu.addAction(self.trUtf8('Show syntax error message'), |
967 self.marginMenu.addAction(self.trUtf8('Show syntax error message'), |
951 self.__showSyntaxError) |
968 self.__showSyntaxError) |
952 self.marginMenuActs["ClearSyntaxError"] = \ |
969 self.marginMenuActs["ClearSyntaxError"] = \ |
953 self.marginMenu.addAction(self.trUtf8('Clear syntax error'), |
970 self.marginMenu.addAction(self.trUtf8('Clear syntax error'), |
954 self.clearSyntaxError) |
971 self.clearSyntaxError) |
|
972 self.marginMenu.addSeparator() |
|
973 self.marginMenuActs["NextWarningMarker"] = \ |
|
974 self.marginMenu.addAction(self.trUtf8("Next warning"), |
|
975 self.nextFlakesWarning) |
|
976 self.marginMenuActs["PreviousWarningMarker"] = \ |
|
977 self.marginMenu.addAction(self.trUtf8("Previous warning"), |
|
978 self.previousFlakesWarning) |
|
979 self.marginMenuActs["ShowWarning"] = \ |
|
980 self.marginMenu.addAction(self.trUtf8('Show warning message'), |
|
981 self.__showFlakesWarning) |
|
982 self.marginMenuActs["ClearWarnings"] = \ |
|
983 self.marginMenu.addAction(self.trUtf8('Clear warnings'), |
|
984 self.clearFlakesWarnings) |
955 self.marginMenu.addSeparator() |
985 self.marginMenu.addSeparator() |
956 self.marginMenuActs["Breakpoint"] = \ |
986 self.marginMenuActs["Breakpoint"] = \ |
957 self.marginMenu.addAction(self.trUtf8('Toggle breakpoint'), |
987 self.marginMenu.addAction(self.trUtf8('Toggle breakpoint'), |
958 self.menuToggleBreakpoint) |
988 self.menuToggleBreakpoint) |
959 self.marginMenuActs["TempBreakpoint"] = \ |
989 self.marginMenuActs["TempBreakpoint"] = \ |
3891 else: |
3925 else: |
3892 self.marginMenuActs["GotoSyntaxError"].setEnabled(False) |
3926 self.marginMenuActs["GotoSyntaxError"].setEnabled(False) |
3893 self.marginMenuActs["ClearSyntaxError"].setEnabled(False) |
3927 self.marginMenuActs["ClearSyntaxError"].setEnabled(False) |
3894 self.marginMenuActs["ShowSyntaxError"].setEnabled(False) |
3928 self.marginMenuActs["ShowSyntaxError"].setEnabled(False) |
3895 |
3929 |
|
3930 if len(self.warnings): |
|
3931 self.marginMenuActs["NextWarningMarker"].setEnabled(True) |
|
3932 self.marginMenuActs["PreviousWarningMarker"].setEnabled(True) |
|
3933 self.marginMenuActs["ClearWarnings"].setEnabled(True) |
|
3934 if self.markersAtLine(self.line) & (1 << self.warning): |
|
3935 self.marginMenuActs["ShowWarning"].setEnabled(True) |
|
3936 else: |
|
3937 self.marginMenuActs["ShowWarning"].setEnabled(False) |
|
3938 else: |
|
3939 self.marginMenuActs["NextWarningMarker"].setEnabled(False) |
|
3940 self.marginMenuActs["PreviousWarningMarker"].setEnabled(True) |
|
3941 self.marginMenuActs["ClearWarnings"].setEnabled(False) |
|
3942 self.marginMenuActs["ShowWarning"].setEnabled(False) |
|
3943 |
3896 if self.notcoveredMarkers: |
3944 if self.notcoveredMarkers: |
3897 self.marginMenuActs["NextCoverageMarker"].setEnabled(True) |
3945 self.marginMenuActs["NextCoverageMarker"].setEnabled(True) |
3898 self.marginMenuActs["PreviousCoverageMarker"].setEnabled(True) |
3946 self.marginMenuActs["PreviousCoverageMarker"].setEnabled(True) |
3899 else: |
3947 else: |
3900 self.marginMenuActs["NextCoverageMarker"].setEnabled(False) |
3948 self.marginMenuActs["NextCoverageMarker"].setEnabled(False) |
3998 """ |
4046 """ |
3999 Private method to perform an automatic syntax check of the file. |
4047 Private method to perform an automatic syntax check of the file. |
4000 """ |
4048 """ |
4001 if Preferences.getEditor("AutoCheckSyntax"): |
4049 if Preferences.getEditor("AutoCheckSyntax"): |
4002 self.clearSyntaxError() |
4050 self.clearSyntaxError() |
|
4051 self.clearFlakesWarnings() |
4003 if self.isPy3File(): |
4052 if self.isPy3File(): |
4004 syntaxError, _fn, errorline, _code, _error = \ |
4053 syntaxError, _fn, errorline, _code, _error = \ |
4005 Utilities.compile(self.fileName, self.text()) |
4054 Utilities.compile(self.fileName, self.text()) |
4006 if syntaxError: |
4055 if syntaxError: |
4007 self.toggleSyntaxError(int(errorline), 1, _error) |
4056 self.toggleSyntaxError(int(errorline), True, _error) |
|
4057 else: |
|
4058 if Preferences.getFlakes("IncludeInSyntaxCheck"): |
|
4059 ignoreStarImportWarnings = \ |
|
4060 Preferences.getFlakes("IgnoreStarImportWarnings") |
|
4061 warnings = Checker(self.text(), self.fileName) |
|
4062 warnings.messages.sort(key = lambda a: a.lineno) |
|
4063 for warning in warnings.messages: |
|
4064 if ignoreStarImportWarnings and \ |
|
4065 isinstance(warning, ImportStarUsed): |
|
4066 continue |
|
4067 |
|
4068 _fn, lineno, message = warning.getMessageData() |
|
4069 self.toggleFlakesWarning(lineno, True, message) |
4008 |
4070 |
4009 def __showCodeMetrics(self): |
4071 def __showCodeMetrics(self): |
4010 """ |
4072 """ |
4011 Private method to handle the code metrics context menu action. |
4073 Private method to handle the code metrics context menu action. |
4012 """ |
4074 """ |
4314 break |
4376 break |
4315 else: |
4377 else: |
4316 QMessageBox.critical(None, |
4378 QMessageBox.critical(None, |
4317 self.trUtf8("Syntax Error"), |
4379 self.trUtf8("Syntax Error"), |
4318 self.trUtf8("No syntax error message available.")) |
4380 self.trUtf8("No syntax error message available.")) |
|
4381 |
|
4382 ############################################################################ |
|
4383 ## Flakes warning handling methods below |
|
4384 ############################################################################ |
|
4385 |
|
4386 def toggleFlakesWarning(self, line, warning, msg = ""): |
|
4387 """ |
|
4388 Public method to toggle a flakes warning indicator. |
|
4389 |
|
4390 @param line line number of the flakes warning |
|
4391 @param erwarningror flag indicating if the warning marker should be |
|
4392 set or deleted (boolean) |
|
4393 @param msg warning message (string) |
|
4394 """ |
|
4395 if line == 0: |
|
4396 line = 1 |
|
4397 # hack to show a warning marker, if line is reported to be 0 |
|
4398 if warning: |
|
4399 # set a new warning marker |
|
4400 markers = self.markersAtLine(line - 1) |
|
4401 if not (markers & (1 << self.warning)): |
|
4402 handle = self.markerAdd(line - 1, self.warning) |
|
4403 self.warnings[handle] = msg |
|
4404 self.emit(SIGNAL('syntaxerrorToggled'), self) |
|
4405 else: |
|
4406 for handle in list(self.warnings.keys()): |
|
4407 if self.markerLine(handle) == line - 1: |
|
4408 del self.warnings[handle] |
|
4409 self.markerDeleteHandle(handle) |
|
4410 self.emit(SIGNAL('syntaxerrorToggled'), self) |
|
4411 |
|
4412 def getFlakesWarnings(self): |
|
4413 """ |
|
4414 Public method to retrieve the flakes warning markers. |
|
4415 |
|
4416 @return sorted list of all lines containing a flakes warning |
|
4417 (list of integer) |
|
4418 """ |
|
4419 fwlist = [] |
|
4420 for handle in list(self.warnings.keys()): |
|
4421 fwlist.append(self.markerLine(handle) + 1) |
|
4422 |
|
4423 fwlist.sort() |
|
4424 return fwlist |
|
4425 |
|
4426 def hasFlakesWarnings(self): |
|
4427 """ |
|
4428 Public method to check for the presence of flakes warnings. |
|
4429 |
|
4430 @return flag indicating the presence of flakes warnings (boolean) |
|
4431 """ |
|
4432 return len(self.warnings) > 0 |
|
4433 |
|
4434 def nextFlakesWarning(self): |
|
4435 """ |
|
4436 Public slot to handle the 'Next warning' context menu action. |
|
4437 """ |
|
4438 line, index = self.getCursorPosition() |
|
4439 if line == self.lines() - 1: |
|
4440 line = 0 |
|
4441 else: |
|
4442 line += 1 |
|
4443 fwline = self.markerFindNext(line, 1 << self.warning) |
|
4444 if fwline < 0: |
|
4445 # wrap around |
|
4446 fwline = self.markerFindNext(0, 1 << self.warning) |
|
4447 if fwline >= 0: |
|
4448 self.setCursorPosition(fwline, 0) |
|
4449 self.ensureLineVisible(fwline) |
|
4450 |
|
4451 def previousFlakesWarning(self): |
|
4452 """ |
|
4453 Public slot to handle the 'Previous warning' context menu action. |
|
4454 """ |
|
4455 line, index = self.getCursorPosition() |
|
4456 if line == 0: |
|
4457 line = self.lines() - 1 |
|
4458 else: |
|
4459 line -= 1 |
|
4460 fwline = self.markerFindPrevious(line, 1 << self.warning) |
|
4461 if fwline < 0: |
|
4462 # wrap around |
|
4463 fwline = self.markerFindPrevious(self.lines() - 1, 1 << self.warning) |
|
4464 if fwline >= 0: |
|
4465 self.setCursorPosition(fwline, 0) |
|
4466 self.ensureLineVisible(fwline) |
|
4467 |
|
4468 def clearFlakesWarnings(self): |
|
4469 """ |
|
4470 Public slot to handle the 'Clear all warnings' context menu action. |
|
4471 """ |
|
4472 for handle in self.warnings: |
|
4473 self.markerDeleteHandle(handle) |
|
4474 self.warnings = {} |
|
4475 self.emit(SIGNAL('syntaxerrorToggled'), self) |
|
4476 |
|
4477 def __showFlakesWarning(self, line = -1): |
|
4478 """ |
|
4479 Private slot to handle the 'Show warning' context menu action. |
|
4480 |
|
4481 @param line line number to show the flakes warning for (integer) |
|
4482 """ |
|
4483 if line == -1: |
|
4484 line = self.line |
|
4485 |
|
4486 for handle in list(self.warnings.keys()): |
|
4487 if self.markerLine(handle) == line: |
|
4488 QMessageBox.warning(None, |
|
4489 self.trUtf8("py3flakes Warning"), |
|
4490 self.warnings[handle]) |
|
4491 break |
|
4492 else: |
|
4493 QMessageBox.warning(None, |
|
4494 self.trUtf8("py3flakes Warning"), |
|
4495 self.trUtf8("No py3flakes warning message available.")) |
4319 |
4496 |
4320 ################################################################# |
4497 ################################################################# |
4321 ## Macro handling methods |
4498 ## Macro handling methods |
4322 ################################################################# |
4499 ################################################################# |
4323 |
4500 |