@@ -88,14 +88,70 @@ def __init__(self, edited_file_paths: Iterable[EditedFilePath], symbol_retriever
8888 self .warning_identities_by_before_path = warning_identities_by_before_path
8989
9090
91+ class GroupedDiagnostics :
92+ def __init__ (self ) -> None :
93+ self ._grouped_diagnostics : dict [str , dict [str , dict [str , list [dict [str , Any ]]]]] = {}
94+
95+ def add (self , relative_path : str , name_path : str , diagnostic : ls_types .Diagnostic ) -> None :
96+ severity_name = self ._diagnostic_severity_name (diagnostic .get ("severity" ))
97+ self ._grouped_diagnostics .setdefault (relative_path , {}).setdefault (severity_name , {}).setdefault (name_path , []).append (
98+ self ._diagnostic_output_dict (diagnostic )
99+ )
100+
101+ def get_dict (self ) -> dict [str , dict [str , dict [str , list [dict [str , Any ]]]]]:
102+ """
103+ Returns a nested dictionary of the form:
104+ {
105+ relative_file_path: {
106+ severity_name: {
107+ name_path: [
108+ diagnostic_dict,
109+ ...
110+ ],
111+ ...
112+ },
113+ ...
114+ },
115+ ...
116+ }
117+ where:
118+ - relative_file_path is the relative path of the file containing the diagnostic
119+ - severity_name is the name of the diagnostic severity (e.g. "Warning", "Error")
120+ - name_path is the name path of the symbol that owns the diagnostic (or "<file>" if no owner symbol was found)
121+ - diagnostic_dict is a dictionary containing the diagnostic's message, range, and optionally code and source
122+ """
123+ return self ._grouped_diagnostics
124+
125+ @staticmethod
126+ def _diagnostic_severity_name (severity : int | None ) -> str :
127+ if severity is None :
128+ return "Unknown"
129+ try :
130+ return DiagnosticSeverity (severity ).name
131+ except ValueError :
132+ return f"Severity_{ severity } "
133+
134+ @staticmethod
135+ def _diagnostic_output_dict (diagnostic : ls_types .Diagnostic ) -> dict [str , Any ]:
136+ result : dict [str , Any ] = {
137+ "message" : diagnostic ["message" ],
138+ "range" : diagnostic ["range" ],
139+ }
140+ if "code" in diagnostic :
141+ result ["code" ] = diagnostic ["code" ]
142+ if "source" in diagnostic :
143+ result ["source" ] = diagnostic ["source" ]
144+ return result
145+
146+
91147class DiagnosticsDiff :
92148 def __init__ (
93149 self ,
94150 before_snapshot : PublishedDiagnosticsSnapshot ,
95151 edited_files : Iterable [EditedFilePath ],
96152 symbol_retriever : "LanguageServerSymbolRetriever" ,
97153 ):
98- grouped_result : dict [ str , dict [ str , dict [ str , list [ dict [ str , Any ]]]]] = {}
154+ grouped_diagnostics = GroupedDiagnostics ()
99155
100156 for edited_file_path in edited_files :
101157 try :
@@ -139,64 +195,9 @@ def __init__(
139195 column = diagnostic_start ["character" ],
140196 )
141197 name_path = owner_symbol .get_name_path () if owner_symbol is not None else "<file>"
142- self . _add_grouped_diagnostic ( grouped_result , edited_file_path .after_relative_path , name_path , diagnostic )
198+ grouped_diagnostics . add ( edited_file_path .after_relative_path , name_path , diagnostic )
143199
144- self ._grouped_result = grouped_result
200+ self ._grouped_diagnostics = grouped_diagnostics
145201
146- def get_grouped_diagnostics (self ) -> dict [str , dict [str , dict [str , list [dict [str , Any ]]]]]:
147- """
148- Returns a nested dictionary of the form:
149- {
150- relative_file_path: {
151- severity_name: {
152- name_path: [
153- diagnostic_dict,
154- ...
155- ],
156- ...
157- },
158- ...
159- },
160- ...
161- }
162- where:
163- - relative_file_path is the relative path of the file containing the diagnostic
164- - severity_name is the name of the diagnostic severity (e.g. "Warning", "Error")
165- - name_path is the name path of the symbol that owns the diagnostic (or "<file>" if no owner symbol was found)
166- - diagnostic_dict is a dictionary containing the diagnostic's message, range, and optionally code and source
167- """
168- return self ._grouped_result
169-
170- @classmethod
171- def _add_grouped_diagnostic (
172- cls ,
173- grouped_result : dict [str , dict [str , dict [str , list [dict [str , Any ]]]]],
174- relative_path : str ,
175- name_path : str ,
176- diagnostic : ls_types .Diagnostic ,
177- ) -> None :
178- severity_name = cls ._diagnostic_severity_name (diagnostic .get ("severity" ))
179- grouped_result .setdefault (relative_path , {}).setdefault (severity_name , {}).setdefault (name_path , []).append (
180- cls ._diagnostic_output_dict (diagnostic )
181- )
182-
183- @staticmethod
184- def _diagnostic_severity_name (severity : int | None ) -> str :
185- if severity is None :
186- return "Unknown"
187- try :
188- return DiagnosticSeverity (severity ).name
189- except ValueError :
190- return f"Severity_{ severity } "
191-
192- @staticmethod
193- def _diagnostic_output_dict (diagnostic : ls_types .Diagnostic ) -> dict [str , Any ]:
194- result : dict [str , Any ] = {
195- "message" : diagnostic ["message" ],
196- "range" : diagnostic ["range" ],
197- }
198- if "code" in diagnostic :
199- result ["code" ] = diagnostic ["code" ]
200- if "source" in diagnostic :
201- result ["source" ] = diagnostic ["source" ]
202- return result
202+ def get_grouped_diagnostics (self ) -> GroupedDiagnostics :
203+ return self ._grouped_diagnostics
0 commit comments