forked from rescript-lang/rescript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbsb_db_util.ml
138 lines (128 loc) · 4.66 KB
/
bsb_db_util.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
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
(* Copyright (C) 2015-2016 Bloomberg Finance L.P.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition to the permissions granted to you by the LGPL, you may combine
* or link a "work that uses the Library" with a publicly distributed version
* of this file to produce a combined library or application, then distribute
* that combined work under the terms of your choosing, with no requirement
* to comply with the obligations normally placed on you by section 4 of the
* LGPL version 3 (or the corresponding section of a later version of the LGPL
* should you choose to use a later version).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
type module_info = Bsb_db.module_info
type t = Bsb_db.map
(* type case = Bsb_db.case *)
let conflict_module_info modname (a : module_info) (b : module_info) =
Bsb_exception.conflict_module
modname
a.dir
b.dir
(* merge data info from two directories*)
let merge (acc : t) (sources : t) : t =
Map_string.merge acc sources (fun modname k1 k2 ->
match k1 , k2 with
| None , None ->
assert false
| Some a, Some b ->
conflict_module_info modname
a
b
| Some v, None -> Some v
| None, Some v -> Some v
)
let sanity_check (map : t) =
Map_string.iter map (fun m module_info ->
if module_info.info = Intf then
Bsb_exception.no_implementation m
)
(* invariant check:
ml and mli should have the same case, same path
*)
let check (x : module_info)
name_sans_extension
case
syntax_kind
(module_info : Bsb_db.info)
=
let x_ml_info = x.info in
(if x.name_sans_extension <> name_sans_extension
|| x.case <> case
|| x.syntax_kind <> syntax_kind
|| x_ml_info = module_info
|| x_ml_info = Impl_intf
then
Bsb_exception.invalid_spec
(Printf.sprintf
"implementation and interface have different path names or different cases %s vs %s"
x.name_sans_extension name_sans_extension));
x.info <- Impl_intf;
x
let warning_unused_file : _ format =
"@{<warning>IGNORED@}: file %s under %s is ignored because it can't be turned into a valid module name. The build system transforms a file name into a module name by upper-casing the first letter@."
let add_basename
~(dir:string)
(map : t)
?(error_on_invalid_suffix)
basename : t =
let info = ref Bsb_db.Impl in
let syntax_kind = ref Bsb_db.Ml in
let invalid_suffix = ref false in
let file_suffix = Ext_filename.get_extension_maybe basename in
(match () with
| _ when file_suffix = Literals.suffix_ml ->
()
| _ when file_suffix = Literals.suffix_res ->
syntax_kind := Res
| _ when file_suffix = Literals.suffix_re ->
syntax_kind := Reason
| _ when file_suffix = Literals.suffix_mli ->
info := Intf
| _ when file_suffix = Literals.suffix_resi ->
info := Intf;
syntax_kind := Res
| _ when file_suffix = Literals.suffix_rei ->
info := Intf;
syntax_kind := Reason
| _ ->
invalid_suffix := true
);
let info= !info in
let syntax_kind = !syntax_kind in
let invalid_suffix = !invalid_suffix in
if invalid_suffix then
match error_on_invalid_suffix with
| None -> map
| Some loc ->
Bsb_exception.errorf ~loc:loc
"invalid suffix %s" basename
else
match Ext_filename.as_module ~basename:(Filename.basename basename) with
| None ->
Bsb_log.warn warning_unused_file basename dir;
map
| Some {module_name; case} ->
let name_sans_extension =
Filename.concat dir (Ext_filename.chop_extension_maybe basename) in
let dir = Filename.dirname name_sans_extension in
Map_string.adjust
map
module_name
(fun opt_module_info ->
match opt_module_info with
| None ->
{dir ; name_sans_extension ; info ; syntax_kind ; case }
| Some x ->
check x name_sans_extension case syntax_kind info
)