@@ -264,6 +264,62 @@ type error_resolution_stat = {
264264 time_to_resolve_all_subtyping_errors_in_one_file : float option ;
265265}
266266
267+ type per_error_info = {
268+ error_code : string ;
269+ line_agnostic_hash : string ;
270+ error_message : string option ;
271+ }
272+
273+ type per_file_errors = {
274+ file_path : string ;
275+ errors : per_error_info list ;
276+ }
277+
278+ let compute_per_file_errors ~with_context_limit collated_errors =
279+ let open Flow_errors_utils in
280+ let context_count = ref 0 in
281+ let process_errors filename errors acc =
282+ if ConcreteLocPrintableErrorSet. is_empty errors then
283+ acc
284+ else
285+ let file_path =
286+ match filename with
287+ | File_key. SourceFile s
288+ | File_key. JsonFile s
289+ | File_key. ResourceFile s
290+ | File_key. LibFile s ->
291+ s
292+ in
293+ let error_infos =
294+ ConcreteLocPrintableErrorSet. fold
295+ (fun error acc ->
296+ let lsp = Lsp_output. lsp_of_error ~has_detailed_diagnostics: false error in
297+ let code_str = lsp.Lsp_output. code in
298+ let hash_input = code_str ^ " :" ^ lsp.Lsp_output. message in
299+ let hash = Printf. sprintf " %x" (Hashtbl. hash hash_input) in
300+ let error_message =
301+ if ! context_count < with_context_limit then begin
302+ context_count := ! context_count + 1 ;
303+ let msg = lsp.Lsp_output. message in
304+ let msg =
305+ if String. length msg > 400 then
306+ String. sub msg 0 400 ^ " ..."
307+ else
308+ msg
309+ in
310+ Some msg
311+ end else
312+ None
313+ in
314+ { error_code = code_str; line_agnostic_hash = hash; error_message } :: acc)
315+ errors
316+ []
317+ in
318+ { file_path; errors = error_infos } :: acc
319+ in
320+ let acc = FilenameMap. fold process_errors collated_errors.collated_merge_errors [] in
321+ FilenameMap. fold process_errors collated_errors.collated_local_errors acc
322+
267323let update_error_state_timestamps collated_errors =
268324 let current_time = Unix. gettimeofday () in
269325 let init_timestamps = collated_errors.error_state_timestamps in
0 commit comments