Source file ExtendedUnit.ml

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
(** An extension of [Unit.u] that includes the [ModuleUnit.t]. That extension
    allows it to build a dependency graph based on [ModuleUnit.t]. *)

type ext2 = {
  signature : Module.signature;
  dependencies : Deps.t;
  module_unit : ModuleUnit.t;
  mods : MlFront_Core.UnitMods.t;
}

let pp_ext2 ppf { signature; dependencies; module_unit; mods = _ } =
  Format.fprintf ppf "signature:%a@ deps:%a@ unit:%a" Module.pp_signature
    signature Deps.pp dependencies ModuleUnit.pp module_unit

type u2 = ext2 Unit.t

let pp_u2 ppf u2 = (DerivUnit.pp pp_ext2) ppf u2

let of_unit_u (u : Unit.u) ({ load_mods; _ } as module_unit : ModuleUnit.t)
    analysis_mods =
  let full_mods =
    match load_mods with
    | None -> analysis_mods
    | Some load_mods -> MlFront_Core.UnitMods.union load_mods analysis_mods
  in
  {
    u with
    more =
      {
        signature = u.more.signature;
        dependencies = u.more.dependencies;
        module_unit;
        mods = full_mods;
      };
  }

let dump_units (units : u2 list) =
  if !CodeptLog.debug_solver then
    CodeptLog.debug (fun l -> l "unit:@ %a" (Fmt.list pp_u2) units)

let calculate_dependency_graph (units : u2 list) : ModuleUnit.t list DepGraph.t
    =
  let module_unit_by_path : ModuleUnit.t Namespaced.map =
    List.fold_left
      (fun graph (u2 : u2) ->
        Namespaced.Map.add u2.path u2.more.module_unit graph)
      Namespaced.Map.empty units
  in
  (* merge .ml and .mli into single possibly duplicative list of dependencies *)
  let dependencies_by_module_id : Namespaced.t list DepGraph.t =
    List.fold_left
      (fun graph (u2 : u2) ->
        DepGraph.update u2.more.module_unit
          (function
            | None -> Some (Deps.paths u2.more.dependencies)
            | Some existing -> Some (existing @ Deps.paths u2.more.dependencies))
          graph)
      DepGraph.empty units
  in
  (* fixup duplicates *)
  let unique_dependencies_by_module_id : Namespaced.t list DepGraph.t =
    DepGraph.map
      (fun deps -> List.sort_uniq Namespaced.compare deps)
      dependencies_by_module_id
  in
  DepGraph.map
    (fun deps ->
      (* Some dependencies will be to MlFront Runtime modules like
         [Tr1StdlibV414_Base]. Those are part of [.cma] files and will
         not be present in the ml/mli-based [module_id_by_path]. *)
      List.filter_map
        (fun dep -> Namespaced.Map.find_opt dep module_unit_by_path)
        deps)
    unique_dependencies_by_module_id