1515from mypy .nodes import Context
1616from mypy .options import Options
1717from mypy .scope import Scope
18+ from mypy .typeops import make_simplified_union
19+ from mypy .types import Type
1820from mypy .util import DEFAULT_SOURCE_OFFSET , is_typeshed_file
1921from mypy .version import __version__ as mypy_version
2022
@@ -166,18 +168,24 @@ class ErrorWatcher:
166168 out by one of the ErrorWatcher instances.
167169 """
168170
171+ # public attribute for the special treatment of `reveal_type` by
172+ # `MessageBuilder.reveal_type`:
173+ filter_revealed_type : bool
174+
169175 def __init__ (
170176 self ,
171177 errors : Errors ,
172178 * ,
173179 filter_errors : bool | Callable [[str , ErrorInfo ], bool ] = False ,
174180 save_filtered_errors : bool = False ,
175181 filter_deprecated : bool = False ,
182+ filter_revealed_type : bool = False
176183 ) -> None :
177184 self .errors = errors
178185 self ._has_new_errors = False
179186 self ._filter = filter_errors
180187 self ._filter_deprecated = filter_deprecated
188+ self .filter_revealed_type = filter_revealed_type
181189 self ._filtered : list [ErrorInfo ] | None = [] if save_filtered_errors else None
182190
183191 def __enter__ (self ) -> Self :
@@ -236,15 +244,15 @@ class IterationDependentErrors:
236244 # the error report occurs but really all unreachable lines.
237245 unreachable_lines : list [set [int ]]
238246
239- # One set of revealed types for each `reveal_type` statement. Each created set can
240- # grow during the iteration. Meaning of the tuple items: function_or_member, line ,
241- # column, end_line, end_column:
242- revealed_types : dict [tuple [str | None , int , int , int , int ], set [ str ]]
247+ # One list of revealed types for each `reveal_type` statement. Each created list
248+ # can grow during the iteration. Meaning of the tuple items: line, column ,
249+ # end_line, end_column:
250+ revealed_types : dict [tuple [int , int , int | None , int | None ], list [ Type ]]
243251
244252 def __init__ (self ) -> None :
245253 self .uselessness_errors = []
246254 self .unreachable_lines = []
247- self .revealed_types = defaultdict (set )
255+ self .revealed_types = defaultdict (list )
248256
249257
250258class IterationErrorWatcher (ErrorWatcher ):
@@ -287,15 +295,6 @@ def on_error(self, file: str, info: ErrorInfo) -> bool:
287295 iter_errors .unreachable_lines [- 1 ].update (range (info .line , info .end_line + 1 ))
288296 return True
289297
290- if info .code == codes .MISC and info .message .startswith ("Revealed type is " ):
291- key = info .function_or_member , info .line , info .column , info .end_line , info .end_column
292- types = info .message .split ('"' )[1 ]
293- if types .startswith ("Union[" ):
294- iter_errors .revealed_types [key ].update (types [6 :- 1 ].split (", " ))
295- else :
296- iter_errors .revealed_types [key ].add (types )
297- return True
298-
299298 return super ().on_error (file , info )
300299
301300 def yield_error_infos (self ) -> Iterator [tuple [str , Context , ErrorCode ]]:
@@ -318,21 +317,14 @@ def yield_error_infos(self) -> Iterator[tuple[str, Context, ErrorCode]]:
318317 context .end_column = error_info [5 ]
319318 yield error_info [1 ], context , error_info [0 ]
320319
321- def yield_note_infos (self , options : Options ) -> Iterator [tuple [str , Context ]]:
320+ def yield_note_infos (self , options : Options ) -> Iterator [tuple [Type , Context ]]:
322321 """Yield all types revealed in at least one iteration step."""
323322
324323 for note_info , types in self .iteration_dependent_errors .revealed_types .items ():
325- sorted_ = sorted (types , key = lambda typ : typ .lower ())
326- if len (types ) == 1 :
327- revealed = sorted_ [0 ]
328- elif options .use_or_syntax ():
329- revealed = " | " .join (sorted_ )
330- else :
331- revealed = f"Union[{ ', ' .join (sorted_ )} ]"
332- context = Context (line = note_info [1 ], column = note_info [2 ])
333- context .end_line = note_info [3 ]
334- context .end_column = note_info [4 ]
335- yield f'Revealed type is "{ revealed } "' , context
324+ context = Context (line = note_info [0 ], column = note_info [1 ])
325+ context .end_line = note_info [2 ]
326+ context .end_column = note_info [3 ]
327+ yield make_simplified_union (types ), context
336328
337329
338330class Errors :
@@ -596,18 +588,20 @@ def _add_error_info(self, file: str, info: ErrorInfo) -> None:
596588 if info .code in (IMPORT , IMPORT_UNTYPED , IMPORT_NOT_FOUND ):
597589 self .seen_import_error = True
598590
591+ @property
592+ def watchers (self ) -> Iterator [ErrorWatcher ]:
593+ """Yield the `ErrorWatcher` stack from top to bottom."""
594+ i = len (self ._watchers )
595+ while i > 0 :
596+ i -= 1
597+ yield self ._watchers [i ]
598+
599599 def _filter_error (self , file : str , info : ErrorInfo ) -> bool :
600600 """
601601 process ErrorWatcher stack from top to bottom,
602602 stopping early if error needs to be filtered out
603603 """
604- i = len (self ._watchers )
605- while i > 0 :
606- i -= 1
607- w = self ._watchers [i ]
608- if w .on_error (file , info ):
609- return True
610- return False
604+ return any (w .on_error (file , info ) for w in self .watchers )
611605
612606 def add_error_info (self , info : ErrorInfo ) -> None :
613607 file , lines = info .origin
0 commit comments