@@ -104,40 +104,114 @@ let print_filename ppf file =
104
104
let reset () =
105
105
num_loc_lines := 0
106
106
107
- let (msg_file, msg_line, msg_chars, msg_to, msg_colon) =
108
- (" File \" " , " \" , line " , " , characters " , " -" , " :" )
109
-
110
107
(* return file, line, char from the given position *)
111
108
let get_pos_info pos =
112
109
(pos.pos_fname, pos.pos_lnum, pos.pos_cnum - pos.pos_bol)
113
110
;;
114
111
115
112
let setup_colors () =
116
- Misc.Color. setup ! Clflags. color
117
-
118
- let print_loc ppf loc =
113
+ Misc.Color. setup ! Clflags. color;
114
+ Code_frame. setup ! Clflags. color
115
+
116
+ (* ocaml's reported line/col numbering is horrible and super error-prone
117
+ when being handled programmatically (or humanly for that matter. If you're
118
+ an ocaml contributor reading this: who the heck reads the character count
119
+ starting from the first erroring character?) *)
120
+ let normalize_range loc =
121
+ (* TODO: lots of the handlings here aren't needed anymore because the new
122
+ rescript syntax has much stronger invariants regarding positions, e.g.
123
+ no -1 *)
124
+ let (_, start_line, start_char) = get_pos_info loc.loc_start in
125
+ let (_, end_line, end_char) = get_pos_info loc.loc_end in
126
+ (* line is 1-indexed, column is 0-indexed. We convert all of them to 1-indexed to avoid confusion *)
127
+ (* start_char is inclusive, end_char is exclusive *)
128
+ if start_char == - 1 || end_char == - 1 then
129
+ (* happens sometimes. Syntax error for example *)
130
+ None
131
+ else if start_line = end_line && start_char > = end_char then
132
+ (* in some errors, starting char and ending char can be the same. But
133
+ since ending char was supposed to be exclusive, here it might end up
134
+ smaller than the starting char if we naively did start_char + 1 to
135
+ just the starting char and forget ending char *)
136
+ let same_char = start_char + 1 in
137
+ Some ((start_line, same_char), (end_line, same_char))
138
+ else
139
+ (* again: end_char is exclusive, so +1-1=0 *)
140
+ Some ((start_line, start_char + 1 ), (end_line, end_char))
141
+
142
+ let print_loc ppf (loc : t ) =
119
143
setup_colors () ;
120
- let (file, line, startchar) = get_pos_info loc.loc_start in
121
- let startchar = startchar + 1 in
122
- let endchar = loc.loc_end.pos_cnum - loc.loc_start.pos_cnum + startchar in
123
- begin
124
- fprintf ppf " %s@{<loc>%a%s%i" msg_file print_filename file msg_line line;
125
- if startchar > = 0 then
126
- fprintf ppf " %s%i%s%i" msg_chars startchar msg_to endchar;
127
- fprintf ppf " @}"
128
- end
144
+ let normalized_range = normalize_range loc in
145
+ let dim_loc ppf = function
146
+ | None -> ()
147
+ | Some ((start_line , start_line_start_char ), (end_line , end_line_end_char )) ->
148
+ if start_line = end_line then
149
+ if start_line_start_char = end_line_end_char then
150
+ fprintf ppf " :@{<dim>%i:%i@}" start_line start_line_start_char
151
+ else
152
+ fprintf ppf " :@{<dim>%i:%i-%i@}" start_line start_line_start_char end_line_end_char
153
+ else
154
+ fprintf ppf " :@{<dim>%i:%i-%i:%i@}" start_line start_line_start_char end_line end_line_end_char
155
+ in
156
+ fprintf ppf " @{<filename>%a@}%a" print_filename loc.loc_start.pos_fname dim_loc normalized_range
129
157
;;
130
158
131
- let default_printer ppf loc =
132
- setup_colors () ;
133
- fprintf ppf " @{<loc>%a@}%s@," print_loc loc msg_colon
159
+ let print ~message_kind intro ppf (loc : t ) =
160
+ begin match message_kind with
161
+ | `warning -> fprintf ppf " @[@{<info>%s@}@]@," intro
162
+ | `warning_as_error -> fprintf ppf " @[@{<error>%s@} (configured as error) @]@," intro
163
+ | `error -> fprintf ppf " @[@{<error>%s@}@]@," intro
164
+ end ;
165
+ (* ocaml's reported line/col numbering is horrible and super error-prone
166
+ when being handled programmatically (or humanly for that matter. If you're
167
+ an ocaml contributor reading this: who the heck reads the character count
168
+ starting from the first erroring character?) *)
169
+ let (file, start_line, start_char) = get_pos_info loc.loc_start in
170
+ let (_, end_line, end_char) = get_pos_info loc.loc_end in
171
+ (* line is 1-indexed, column is 0-indexed. We convert all of them to 1-indexed to avoid confusion *)
172
+ (* start_char is inclusive, end_char is exclusive *)
173
+ let normalizedRange =
174
+ (* TODO: lots of the handlings here aren't needed anymore because the new
175
+ rescript syntax has much stronger invariants regarding positions, e.g.
176
+ no -1 *)
177
+ if start_char == - 1 || end_char == - 1 then
178
+ (* happens sometimes. Syntax error for example *)
179
+ None
180
+ else if start_line = end_line && start_char > = end_char then
181
+ (* in some errors, starting char and ending char can be the same. But
182
+ since ending char was supposed to be exclusive, here it might end up
183
+ smaller than the starting char if we naively did start_char + 1 to
184
+ just the starting char and forget ending char *)
185
+ let same_char = start_char + 1 in
186
+ Some ((start_line, same_char), (end_line, same_char))
187
+ else
188
+ (* again: end_char is exclusive, so +1-1=0 *)
189
+ Some ((start_line, start_char + 1 ), (end_line, end_char))
190
+ in
191
+ fprintf ppf " @[%a@]@," print_loc loc;
192
+ match normalizedRange with
193
+ | None -> ()
194
+ | Some _ -> begin
195
+ try
196
+ let src = Ext_io. load_file file in
197
+ (* we're putting the line break `@,` here rather than above, because this
198
+ branch might not be reached (aka no inline file content display) so
199
+ we don't wanna end up with two line breaks in the the consequent *)
200
+ fprintf ppf " @,%s"
201
+ (Code_frame. print
202
+ ~is_warning: (message_kind= `warning )
203
+ ~src
204
+ ~start Pos:loc.loc_start
205
+ ~end Pos:loc.loc_end
206
+ )
207
+ with
208
+ (* this might happen if the file is e.g. "", "_none_" or any of the fake file name placeholders.
209
+ we've already printed the location above, so nothing more to do here. *)
210
+ | Sys_error _ -> ()
211
+ end
134
212
;;
135
213
136
- let printer = ref default_printer
137
- let print ppf loc = ! printer ppf loc
138
-
139
214
let error_prefix = " Error"
140
- let warning_prefix = " Warning"
141
215
142
216
let print_error_prefix ppf =
143
217
setup_colors () ;
@@ -153,30 +227,22 @@ let print_compact ppf loc =
153
227
end
154
228
;;
155
229
156
- let print_error ppf loc =
157
- fprintf ppf " %a%t:" print loc print_error_prefix;
230
+ let print_error intro ppf loc =
231
+ fprintf ppf " %a%t:" ( print ~message_kind: `error intro) loc print_error_prefix;
158
232
;;
159
233
160
- let print_error_cur_file ppf () = print_error ppf (in_file ! input_name);;
161
-
162
234
let default_warning_printer loc ppf w =
163
235
match Warnings. report w with
164
236
| `Inactive -> ()
165
- | `Active { Warnings. number; message; is_error; sub_locs } ->
237
+ | `Active { Warnings. number = _ ; message = _ ; is_error; sub_locs = _ } ->
166
238
setup_colors () ;
167
- fprintf ppf " @[<v>" ;
168
- print ppf loc;
169
- if is_error
170
- then
171
- fprintf ppf " %t (%s %d): %s@," print_error_prefix
172
- (String. uncapitalize_ascii warning_prefix) number message
173
- else fprintf ppf " @{<warning>%s@} %d: %s@," warning_prefix number message;
174
- List. iter
175
- (fun (loc , msg ) ->
176
- if loc <> none then fprintf ppf " %a %s@," print loc msg
177
- )
178
- sub_locs;
179
- fprintf ppf " @]"
239
+ let message_kind = if is_error then `warning_as_error else `warning in
240
+ Format. fprintf ppf " @[<v>@, %a@, %s@,@]@."
241
+ (print ~message_kind (" Warning number " ^ (Warnings. number w |> string_of_int)))
242
+ loc
243
+ (Warnings. message w);
244
+ (* at this point, you can display sub_locs too, from e.g. https://github.com/ocaml/ocaml/commit/f6d53cc38f87c67fbf49109f5fb79a0334bab17a
245
+ but we won't bother for now *)
180
246
;;
181
247
182
248
let warning_printer = ref default_warning_printer ;;
@@ -225,10 +291,13 @@ let pp_ksprintf ?before k fmt =
225
291
k msg)
226
292
ppf fmt
227
293
294
+ (* taken from https://github.com/rescript-lang/ocaml/blob/d4144647d1bf9bc7dc3aadc24c25a7efa3a67915/parsing/location.ml#L354 *)
228
295
(* Shift the formatter's offset by the length of the error prefix, which
229
296
is always added by the compiler after the message has been formatted *)
230
297
let print_phanton_error_prefix ppf =
231
- Format. pp_print_as ppf (String. length error_prefix + 2 (* ": " *) ) " "
298
+ (* modified from the original. We use only 2 indentations for error report
299
+ (see super_error_reporter above) *)
300
+ Format. pp_print_as ppf 2 " "
232
301
233
302
let errorf ?(loc = none) ?(sub = [] ) ?(if_highlight = " " ) fmt =
234
303
pp_ksprintf
@@ -258,11 +327,14 @@ let error_of_exn exn =
258
327
in
259
328
loop ! error_of_exn
260
329
261
-
330
+ (* taken from https://github.com/rescript-lang/ocaml/blob/d4144647d1bf9bc7dc3aadc24c25a7efa3a67915/parsing/location.ml#L380 *)
331
+ (* This is the error report entry point. We'll replace the default reporter with this one. *)
262
332
let rec default_error_reporter ppf ({loc; msg; sub} ) =
263
- fprintf ppf " @[<v>%a %s" print_error loc msg;
264
- List. iter (Format. fprintf ppf " @,@[<2>%a@]" default_error_reporter) sub;
265
- fprintf ppf " @]"
333
+ setup_colors () ;
334
+ (* open a vertical box. Everything in our message is indented 2 spaces *)
335
+ Format. fprintf ppf " @[<v>@, %a@, %s@,@]" (print ~message_kind: `error " We've found a bug for you!" ) loc msg;
336
+ List. iter (Format. fprintf ppf " @,@[%a@]" default_error_reporter) sub
337
+ (* no need to flush here; location's report_exception (which uses this ultimately) flushes *)
266
338
267
339
let error_reporter = ref default_error_reporter
268
340
0 commit comments