20
20
# Show error codes for some note-level messages (these usually appear alone
21
21
# and not as a comment for a previous error-level message).
22
22
SHOW_NOTE_CODES : Final = {codes .ANNOTATION_UNCHECKED }
23
+
24
+ # Do not add notes with links to error code docs to errors with these codes.
25
+ # We can tweak this set as we get more experience about what is helpful and what is not.
26
+ HIDE_LINK_CODES : Final = {
27
+ # This is a generic error code, so it has no useful docs
28
+ codes .MISC ,
29
+ # These are trivial and have some custom notes (e.g. for list being invariant)
30
+ codes .ASSIGNMENT ,
31
+ codes .ARG_TYPE ,
32
+ codes .RETURN_VALUE ,
33
+ # Undefined name/attribute errors are self-explanatory
34
+ codes .ATTR_DEFINED ,
35
+ codes .NAME_DEFINED ,
36
+ # Overrides have a custom link to docs
37
+ codes .OVERRIDE ,
38
+ }
39
+
23
40
allowed_duplicates : Final = ["@overload" , "Got:" , "Expected:" ]
24
41
42
+ BASE_RTD_URL : Final = "https://mypy.rtfd.io/en/stable/_refs.html#code"
43
+
25
44
# Keep track of the original error code when the error code of a message is changed.
26
45
# This is used to give notes about out-of-date "type: ignore" comments.
27
46
original_error_codes : Final = {codes .LITERAL_REQ : codes .MISC , codes .TYPE_ABSTRACT : codes .MISC }
@@ -107,6 +126,7 @@ def __init__(
107
126
allow_dups : bool ,
108
127
origin : tuple [str , Iterable [int ]] | None = None ,
109
128
target : str | None = None ,
129
+ priority : int = 0 ,
110
130
) -> None :
111
131
self .import_ctx = import_ctx
112
132
self .file = file
@@ -125,6 +145,7 @@ def __init__(
125
145
self .allow_dups = allow_dups
126
146
self .origin = origin or (file , [line ])
127
147
self .target = target
148
+ self .priority = priority
128
149
129
150
130
151
# Type used internally to represent errors:
@@ -530,6 +551,35 @@ def add_error_info(self, info: ErrorInfo) -> None:
530
551
allow_dups = False ,
531
552
)
532
553
self ._add_error_info (file , note )
554
+ if (
555
+ self .options .show_error_code_links
556
+ and not self .options .hide_error_codes
557
+ and info .code is not None
558
+ and info .code not in HIDE_LINK_CODES
559
+ ):
560
+ message = f"See { BASE_RTD_URL } -{ info .code .code } for more info"
561
+ if message in self .only_once_messages :
562
+ return
563
+ self .only_once_messages .add (message )
564
+ info = ErrorInfo (
565
+ import_ctx = info .import_ctx ,
566
+ file = info .file ,
567
+ module = info .module ,
568
+ typ = info .type ,
569
+ function_or_member = info .function_or_member ,
570
+ line = info .line ,
571
+ column = info .column ,
572
+ end_line = info .end_line ,
573
+ end_column = info .end_column ,
574
+ severity = "note" ,
575
+ message = message ,
576
+ code = info .code ,
577
+ blocker = False ,
578
+ only_once = True ,
579
+ allow_dups = False ,
580
+ priority = 20 ,
581
+ )
582
+ self ._add_error_info (file , info )
533
583
534
584
def has_many_errors (self ) -> bool :
535
585
if self .options .many_errors_threshold < 0 :
@@ -1041,6 +1091,34 @@ def sort_messages(self, errors: list[ErrorInfo]) -> list[ErrorInfo]:
1041
1091
1042
1092
# Sort the errors specific to a file according to line number and column.
1043
1093
a = sorted (errors [i0 :i ], key = lambda x : (x .line , x .column ))
1094
+ a = self .sort_within_context (a )
1095
+ result .extend (a )
1096
+ return result
1097
+
1098
+ def sort_within_context (self , errors : list [ErrorInfo ]) -> list [ErrorInfo ]:
1099
+ """For the same location decide which messages to show first/last.
1100
+
1101
+ Currently, we only compare within the same error code, to decide the
1102
+ order of various additional notes.
1103
+ """
1104
+ result = []
1105
+ i = 0
1106
+ while i < len (errors ):
1107
+ i0 = i
1108
+ # Find neighbouring errors with the same position and error code.
1109
+ while (
1110
+ i + 1 < len (errors )
1111
+ and errors [i + 1 ].line == errors [i ].line
1112
+ and errors [i + 1 ].column == errors [i ].column
1113
+ and errors [i + 1 ].end_line == errors [i ].end_line
1114
+ and errors [i + 1 ].end_column == errors [i ].end_column
1115
+ and errors [i + 1 ].code == errors [i ].code
1116
+ ):
1117
+ i += 1
1118
+ i += 1
1119
+
1120
+ # Sort the messages specific to a given error by priority.
1121
+ a = sorted (errors [i0 :i ], key = lambda x : x .priority )
1044
1122
result .extend (a )
1045
1123
return result
1046
1124
0 commit comments