Skip to content

Commit 7880a37

Browse files
committed
Introduce better error handling with feedback
1 parent 5372d08 commit 7880a37

File tree

2 files changed

+60
-49
lines changed

2 files changed

+60
-49
lines changed

src/Main.re

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ let make = (~cil, ~goblint, ~warnings, ~meta, ~stats, ~file_loc) => {
5252
let (goblint_path, parameters) = state |> ParameterUtils.get_parameters;
5353
let (destructured_params, _) = parameters |> ParameterUtils.construct_parameters;
5454

55-
let (history, setHistory) = React.useState(_ => [(destructured_params, Time.get_local_time(), ParameterView.Executed)]);
55+
let (history, setHistory) = React.useState(_ => [(destructured_params, Time.get_local_time(), ParameterView.Executed, "")]);
5656
let (inputValue, setInputValue) = React.useState(_ => destructured_params |> ParameterUtils.concat_parameter_list);
5757
let (disableRun, setDisableRun) = React.useState(_ => false);
5858
let (inputState, setInputState) = React.useState(_ => ParameterView.Ok);

src/ui/panel/ParameterView.re

Lines changed: 59 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ let make = (~goblint_path, ~inputValue, ~setInputValue,~disableRun, ~setDisableR
120120
|> ParameterUtils.construct_parameters
121121
|> ((p,b)) => (p |> ParameterUtils.tuples_from_parameters, b);
122122

123-
react_on_input(tuple_parameter_list, is_malformed, inputValue);
123+
react_on_input(tuple_parameter_list, is_malformed, inputValue)
124124
}
125125

126126
let on_add_parameter = (ev) => {
@@ -162,45 +162,41 @@ let make = (~goblint_path, ~inputValue, ~setInputValue,~disableRun, ~setDisableR
162162

163163
if (!isInvalid) {
164164
let time = Time.get_local_time();
165-
let element = (parameter_list, time, Executing);
165+
let element = (parameter_list, time, Executing, "");
166166

167167
let new_history = List.cons(element, history);
168168

169169
setHistory(_ => new_history);
170170
//setDisableCancel(_ => false);
171171

172-
let modify_history = (result: paramState): unit => {
172+
let modify_history = (result: paramState, response_msg: string): unit => {
173173
let pickedElem = new_history |> List.hd;
174174

175175
if (pickedElem == element) {
176176
let intermediateHistory = new_history |> List.tl;
177-
let new_history = List.cons(((parameter_list, time, result)), intermediateHistory);
177+
let new_history = List.cons(((parameter_list, time, result, response_msg)), intermediateHistory);
178178
setHistory(_ => new_history);
179179
//setDisableCancel(_ => true);
180180
}
181181
}
182182

183-
let inner_config_api_call = (config_body): Lwt.t(paramState) => {
184-
Client.post(config_uri, ~body=config_body, ~headers=headers) >>=
183+
let inner_config_api_call = (config_body): Lwt.t((paramState, string)) => {
184+
Client.post(config_uri, ~body=config_body, ~headers=headers) >>=
185185
((res, body)) => {
186186
let code = res |> Response.status |> Code.code_of_status;
187-
/*let msg_from_body = Cohttp_lwt.Body.to_string(body) >|= (body) => {
188-
Lwt.return(body)
189-
}*/
190-
let _ = Body.drain_body(body);
191-
192-
if (code < 200 || code >= 400) {
193-
Lwt.return(Error);
194-
} else {
195-
Lwt.return(Executed);
196-
};
187+
188+
Cohttp_lwt.Body.to_string(body) >>= (body) => {
189+
if (code < 200 || code >= 400) {
190+
Lwt.return((Error, body));
191+
} else {
192+
Lwt.return((Executed, body));
193+
};
194+
}
197195
};
198196
};
199197

200198
let config_api_call = (config_opts: list((string, string))) => {
201-
if (List.length(config_opts) == 0) {
202-
Lwt.return([Error])
203-
} else {
199+
let config_call_function = () => {
204200
config_opts
205201
|> List.map(((k,v)) => {
206202
`List([`String(k), Yojson.Safe.from_string(v)])
@@ -209,20 +205,27 @@ let make = (~goblint_path, ~inputValue, ~setInputValue,~disableRun, ~setDisableR
209205
})
210206
|> List.map(inner_config_api_call)
211207
|> Lwt.npick;
212-
}
208+
};
209+
210+
let exception_handler = (exc) => {
211+
Lwt.return([(Error, Printexc.to_string(exc))]);
212+
};
213+
214+
Lwt.catch(config_call_function, exception_handler);
213215
};
214216

215-
let inner_analyze_api_call = (analyze_body): Lwt.t(paramState) => {
217+
let inner_analyze_api_call = (analyze_body) => {
216218
Client.post(analyze_uri, ~body=analyze_body, ~headers=headers) >>=
217219
((res, body)) => {
218220
let code = res |> Response.status |> Code.code_of_status;
219-
let _ = Body.drain_body(body);
220221

221-
if (code < 200 || code >= 400) {
222-
Lwt.return(Error);
223-
} else {
224-
Lwt.return(Executed);
225-
};
222+
Cohttp_lwt.Body.to_string(body) >>= (body) => {
223+
if (code < 200 || code >= 400) {
224+
Lwt.return((Error, body));
225+
} else {
226+
Lwt.return((Executed, body));
227+
};
228+
}
226229
};
227230
};
228231

@@ -232,25 +235,28 @@ let make = (~goblint_path, ~inputValue, ~setInputValue,~disableRun, ~setDisableR
232235
|> Body.of_string;
233236

234237
let analyze_api_call = () => {
238+
let exception_handler = (exc) => {
239+
Lwt.return((Error, Printexc.to_string(exc)));
240+
};
241+
235242
tuple_parameter_list
236243
|> config_api_call >>=
237244
(result) => {
238-
let result_state =
239-
result
240-
|> List.map(is_successful)
241-
|> List.fold_left((a,b) => a && b, true)
242-
|> ((s) => if (s) { Executed } else { Error });
245+
let result_state = result |> List.find_opt(((state, _)) => state == Error);
243246

244-
Lwt.return(result_state);
247+
switch (result_state) {
248+
| None => Lwt.return((Executed, ""))
249+
| Some(r) => Lwt.return(r)
250+
}
245251
} >>=
246252
(result) => {
247253
switch result {
248-
| Executed => inner_analyze_api_call(analyze_body);
249-
| _ => Lwt.return(Error);
254+
| (Executed, _) => Lwt.catch(() => inner_analyze_api_call(analyze_body), exception_handler);
255+
| (_, msg) => Lwt.return((Error, msg))
250256
}
251257
} >>=
252-
(result) => {
253-
modify_history(result);
258+
((state, msg)) => {
259+
modify_history(state, msg);
254260
Lwt.return()
255261
};
256262
};
@@ -289,18 +295,23 @@ let make = (~goblint_path, ~inputValue, ~setInputValue,~disableRun, ~setDisableR
289295
history
290296
}
291297
}
292-
|> List.mapi((i, (parameter_grouping, time, paramState)) =>
298+
|> List.mapi((i, (parameter_grouping, time, paramState, msg)) =>
293299
{<li key={"params_" ++ string_of_int(i)} className="list-group-item">
294300
<div className="container text-center">
295301
<div className="row">
296-
<div className="col-2">
297-
{switch paramState {
298-
| Executing => <Spinner />
299-
| Canceled => <IconX />
300-
| Executed => <IconCheckmark />
301-
| Error => <IconWarning />
302-
}}
303-
</div>
302+
{switch paramState {
303+
| Error => <div className="col-2" data="tooltip" title=msg style={ReactDOM.Style.make(~cursor="help", ())}><IconWarning /></div>
304+
| _ => {
305+
<div className="col-2">
306+
{switch paramState {
307+
| Executing => <Spinner />
308+
| Canceled => <IconX />
309+
| Executed => <IconCheckmark />
310+
| Error => <IconWarning />
311+
}}
312+
</div>
313+
}
314+
}}
304315
<div className="col-2">
305316
<div className="ms-2">
306317
<IconClock />
@@ -309,7 +320,7 @@ let make = (~goblint_path, ~inputValue, ~setInputValue,~disableRun, ~setDisableR
309320
</div>
310321
<div className="col">
311322
{parameter_grouping |> List.mapi((j,e) => {
312-
<span key={"pill_" ++ string_of_int(j)} className="m-1 badge rounded-pill bg-secondary text" style={ReactDOM.Style.make(~cursor="pointer", ())} onClick=on_add_parameter>
323+
<span key={"pill_" ++ string_of_int(j)} className="m-1 badge rounded-pill bg-secondary text" style={ReactDOM.Style.make(~cursor="copy", ())} onClick=on_add_parameter>
313324
{e |> React.string}
314325
</span>
315326
}) |> React.list}
@@ -331,7 +342,7 @@ let make = (~goblint_path, ~inputValue, ~setInputValue,~disableRun, ~setDisableR
331342
{"Cancel" |> React.string}
332343
</Button>*/
333344

334-
<label data="tooltip" title=goblint_path className="input-group-text" type_="tooltip_path">{"./goblint" |> React.string}</label>
345+
<label data="tooltip" title=goblint_path className="input-group-text" type_="tooltip_path" style={ReactDOM.Style.make(~cursor="help", ())}>{"./goblint" |> React.string}</label>
335346
// Input and tooltip are seperated due to display issues
336347
{switch inputState {
337348
| Malformed

0 commit comments

Comments
 (0)