|
| 1 | +open Std |
| 2 | +open Type_utils |
| 3 | + |
| 4 | +module Kind_info = struct |
| 5 | + type t = { kind : Types.jkind_l; env : Env.t } |
| 6 | + |
| 7 | + let mk ~kind ~env = { kind; env } |
| 8 | + |
| 9 | + let from_type ~env ty = { kind = Ctype.estimate_type_jkind env ty; env } |
| 10 | + |
| 11 | + let to_string ~(verbosity : Mconfig.Verbosity.t) { kind; env } = |
| 12 | + let kind = |
| 13 | + Jkind.normalize ~mode:Require_best |
| 14 | + ~context:(Ctype.mk_jkind_context_check_principal env) |
| 15 | + kind |
| 16 | + in |
| 17 | + let print_with_verbosity ~jkind_verbosity kind = |
| 18 | + Printtyp.wrap_printing_env ~verbosity env (fun () -> |
| 19 | + Format.asprintf "%a" |
| 20 | + (Jkind.format_verbose ~verbosity:jkind_verbosity) |
| 21 | + kind) |
| 22 | + in |
| 23 | + let jkind_verbosity : Jkind.Format_verbosity.t = |
| 24 | + match Mconfig.Verbosity.to_int ~for_smart:0 verbosity with |
| 25 | + | 0 -> Not_verbose |
| 26 | + | 1 -> |
| 27 | + (* When verbosity=1, we should show the [Expanded] jkind. But the [Expanded] jkind |
| 28 | + may be the same as the [Not_verbose] jkind, in which case we want to skip |
| 29 | + directly to the [Expanded_with_all_mod_bounds] jkind. *) |
| 30 | + (* Printing jkinds without with bounds is cheap. *) |
| 31 | + let kind_without_with_bounds = |
| 32 | + { kind with jkind = { kind.jkind with with_bounds = No_with_bounds } } |
| 33 | + in |
| 34 | + let unexpanded_kind = |
| 35 | + print_with_verbosity ~jkind_verbosity:Not_verbose |
| 36 | + kind_without_with_bounds |
| 37 | + in |
| 38 | + let expanded_kind = |
| 39 | + print_with_verbosity ~jkind_verbosity:Expanded |
| 40 | + kind_without_with_bounds |
| 41 | + in |
| 42 | + if String.equal unexpanded_kind expanded_kind then |
| 43 | + Expanded_with_all_mod_bounds |
| 44 | + else Expanded |
| 45 | + | _ -> Expanded_with_all_mod_bounds |
| 46 | + in |
| 47 | + print_with_verbosity ~jkind_verbosity kind |
| 48 | +end |
| 49 | + |
| 50 | +let loc_contains_cursor (loc : Location.t) ~cursor = |
| 51 | + Lexing.compare_pos loc.loc_start cursor < 0 |
| 52 | + && Lexing.compare_pos cursor loc.loc_end < 0 |
| 53 | + |
| 54 | +let enclosings_of_node ~cursor (env, (node : Browse_raw.node)) : |
| 55 | + (Location.t * Kind_info.t) list = |
| 56 | + match node with |
| 57 | + | Pattern pattern -> |
| 58 | + [ (pattern.pat_loc, Kind_info.from_type ~env pattern.pat_type) ] |
| 59 | + | Expression expr -> |
| 60 | + [ (expr.exp_loc, Kind_info.from_type ~env expr.exp_type) ] |
| 61 | + | Core_type core_type -> |
| 62 | + let constr_enclosings = |
| 63 | + match core_type.ctyp_desc with |
| 64 | + | Ttyp_constr (path, ident, _) when loc_contains_cursor ident.loc ~cursor |
| 65 | + -> |
| 66 | + (* TODO: The env here contains placeholder jkinds for types declared in the same |
| 67 | + recursive block, which causes under-approximations to be returned in some |
| 68 | + cases. *) |
| 69 | + let decl = Env.find_type path env in |
| 70 | + [ (ident.loc, Kind_info.mk ~kind:decl.type_jkind ~env) ] |
| 71 | + | _ -> [] |
| 72 | + in |
| 73 | + constr_enclosings |
| 74 | + @ [ (core_type.ctyp_loc, Kind_info.from_type ~env core_type.ctyp_type) ] |
| 75 | + | Type_declaration decl -> |
| 76 | + [ (decl.typ_loc, Kind_info.mk ~kind:decl.typ_type.type_jkind ~env) ] |
| 77 | + | _ -> [] |
| 78 | + |
| 79 | +let from_mbrowse mbrowse ~cursor : (Location.t * Kind_info.t) list = |
| 80 | + List.concat_map mbrowse ~f:(enclosings_of_node ~cursor) |
0 commit comments