|
1 | 1 | open Js_of_ocaml_compiler |
2 | 2 | open Js_of_ocaml_compiler.Stdlib |
3 | 3 |
|
| 4 | +class check_and_warn = |
| 5 | + object |
| 6 | + inherit Js_traverse.free as super |
| 7 | + |
| 8 | + method! merge_info from = |
| 9 | + let def = from#get_def in |
| 10 | + let use = from#get_use in |
| 11 | + let diff = Javascript.IdentSet.diff def use in |
| 12 | + let diff = |
| 13 | + Javascript.IdentSet.fold |
| 14 | + (fun x acc -> |
| 15 | + match x with |
| 16 | + | S { name = Utf8_string.Utf8 s; _ } -> |
| 17 | + if String.starts_with s ~prefix:"_" then acc else s :: acc |
| 18 | + | V _ -> acc) |
| 19 | + diff |
| 20 | + [] |
| 21 | + in |
| 22 | + (match diff with |
| 23 | + | [] -> () |
| 24 | + | l -> |
| 25 | + Warning.warn |
| 26 | + `Unused_js_variable |
| 27 | + "unused variable:@. %s@." |
| 28 | + (String.concat ~sep:", " l)); |
| 29 | + super#merge_info from |
| 30 | + end |
| 31 | + |
| 32 | +let free_variable code = |
| 33 | + if Warning.enabled `Unused_js_variable |
| 34 | + then |
| 35 | + let o = new check_and_warn in |
| 36 | + let _code = o#program code in |
| 37 | + Javascript.IdentSet.fold |
| 38 | + (fun x acc -> |
| 39 | + match x with |
| 40 | + | S { name = Utf8 x; _ } -> StringSet.add x acc |
| 41 | + | V _ -> acc) |
| 42 | + o#get_free |
| 43 | + StringSet.empty |
| 44 | + else |
| 45 | + let free = ref StringSet.empty in |
| 46 | + let o = new Js_traverse.fast_freevar (fun s -> free := StringSet.add s !free) in |
| 47 | + o#program code; |
| 48 | + !free |
| 49 | + |
4 | 50 | let check_js_file fname = |
| 51 | + Warning.werror := true; |
| 52 | + Warning.enable `Unused_js_variable; |
5 | 53 | let c = Fs.read_file fname in |
6 | 54 | let p = |
7 | 55 | try Parse_js.parse (Parse_js.Lexer.of_string ~filename:fname c) |
8 | 56 | with Parse_js.Parsing_error pi -> |
9 | 57 | failwith (Printf.sprintf "cannot parse file %S (l:%d, c:%d)@." fname pi.line pi.col) |
10 | 58 | in |
11 | | - |
12 | | - let free = ref StringSet.empty in |
13 | | - let o = new Js_traverse.fast_freevar (fun s -> free := StringSet.add s !free) in |
14 | | - o#program p; |
15 | | - let freenames = !free in |
| 59 | + let freenames = free_variable p in |
16 | 60 | let freenames = StringSet.diff freenames Reserved.keyword in |
17 | 61 | let freenames = StringSet.diff freenames Reserved.provided in |
18 | 62 | if not (StringSet.is_empty freenames) |
19 | | - then ( |
20 | | - Format.eprintf "Warning: free variables in %S@." fname; |
21 | | - Format.eprintf "vars: %s@." (String.concat ~sep:", " (StringSet.elements freenames)); |
22 | | - exit 2); |
| 63 | + then |
| 64 | + Warning.warn |
| 65 | + `Free_variables_in_primitive |
| 66 | + "free variables in %[email protected]: %a@." |
| 67 | + fname |
| 68 | + (Format.pp_print_list |
| 69 | + ~pp_sep:(fun fmt () -> Format.pp_print_string fmt ", ") |
| 70 | + Format.pp_print_string) |
| 71 | + (StringSet.elements freenames); |
| 72 | + Warning.process_warnings (); |
23 | 73 | () |
24 | 74 |
|
25 | 75 | (* Keep the two variables below in sync with function build_runtime in |
|
0 commit comments