1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
open Std
let errors : (exn list ref * unit Btype.TypeHash.t) option ref = ref None
let monitor_errors' = ref (ref false)
let monitor_errors () =
if !(!monitor_errors') then monitor_errors' := ref false;
!monitor_errors'
let raise_error ?(ignore_unify = false) exn =
!monitor_errors' := true;
match !errors with
| Some (l, _) -> begin
match exn with
| Ctype.Unify _ when ignore_unify -> ()
| Ctype.Unify _ | Failure _ ->
Logger.log ~section:"Typing_aux.raise_error"
~title:(Printexc.exn_slot_name exn) "%a" Logger.fmt (fun fmt ->
Printexc.record_backtrace true;
Format.pp_print_string fmt (Printexc.get_backtrace ()))
| exn -> l := exn :: !l
end
| None -> raise exn
let () = Msupport_parsing.msupport_raise_error := raise_error
exception Resume
let resume_raise exn =
raise_error exn;
raise Resume
let catch_errors warnings caught f =
let warnings' = Warnings.backup () in
let errors' = !errors in
Warnings.restore warnings;
errors := Some (caught, Btype.TypeHash.create 3);
Misc.try_finally f ~always:(fun () ->
errors := errors';
Warnings.restore warnings')
let uncatch_errors f = let_ref errors None f
let erroneous_type_register te =
let te = Types.Transient_expr.coerce te in
match !errors with
| Some (_, h) -> Btype.TypeHash.replace h te ()
| None -> ()
let erroneous_type_check te =
let te = Types.Transient_expr.coerce te in
match !errors with
| Some (_, h) -> Btype.TypeHash.mem h te
| _ -> false
let rec erroneous_expr_check e =
erroneous_type_check e.Typedtree.exp_type
||
match e.Typedtree.exp_desc with
| Typedtree.Texp_ident (p, _, _) when Ident.name (Path.head p) = "_" -> true
| Typedtree.Texp_apply (e', _) -> erroneous_expr_check e'
| _ -> false
exception Warning of Location.t * string
let prerr_warning loc w =
match !errors with
| None -> ()
| Some (l, _) -> (
let ppf, to_string = Format.to_string () in
Location.print_warning loc ppf w;
match to_string () with
| "" -> ()
| s -> l := Warning (loc, s) :: !l)
let prerr_alert loc w =
match !errors with
| None -> ()
| Some (l, _) -> (
let ppf, to_string = Format.to_string () in
Location.print_alert loc ppf w;
match to_string () with
| "" -> ()
| s -> l := Warning (loc, s) :: !l)
let () =
Location.register_error_of_exn (function
| Warning (loc, str) ->
Some (Location.error ~loc ~source:Location.Warning str)
| _ -> None)
let () = Location.prerr_warning_ref := prerr_warning
let () = Location.prerr_alert_ref := prerr_alert
let flush_saved_types () =
match Cmt_format.get_saved_types () with
| [] -> []
| parts ->
Cmt_format.set_saved_types [];
let open Ast_helper in
let pexp = Exp.constant (Saved_parts.store parts) in
let pstr = Str.eval pexp in
[ Attr.mk Saved_parts.attribute (Parsetree.PStr [ pstr ]) ]
let rec get_saved_types_from_attributes = function
| [] -> []
| attr :: attrs ->
let attr, str = Ast_helper.Attr.as_tuple attr in
if attr = Saved_parts.attribute then
let open Parsetree in
begin
match str with
| PStr
({ pstr_desc = Pstr_eval ({ pexp_desc = Pexp_constant key; _ }, _);
_
}
:: _) -> Saved_parts.find key
| _ -> []
end
else get_saved_types_from_attributes attrs
let with_warning_attribute ?warning_attribute f =
match warning_attribute with
| None -> f ()
| Some attr -> Builtin_attributes.warning_scope attr f
let with_saved_types ?warning_attribute ?save_part f =
let saved_types = Cmt_format.get_saved_types () in
Cmt_format.set_saved_types [];
try
let result = with_warning_attribute ?warning_attribute f in
begin
match save_part with
| None -> ()
| Some f -> Cmt_format.set_saved_types (f result :: saved_types)
end;
result
with exn ->
let saved_types' = Cmt_format.get_saved_types () in
Cmt_format.set_saved_types (saved_types' @ saved_types);
reraise exn
let incorrect_attribute =
Ast_helper.Attr.mk (Location.mknoloc "merlin.incorrect") (Parsetree.PStr [])
let recovery_attributes attrs =
let attrs' = incorrect_attribute :: flush_saved_types () in
match attrs with
| [] -> attrs'
| attrs -> attrs' @ attrs