-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSafeNames.ml
137 lines (123 loc) · 3.77 KB
/
SafeNames.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
open Base
open Util
module StringSet = Set
let reservedWords =
StringSet.of_list
(module String)
[
"open";
"private";
"as";
"external";
"public";
"protected";
"string";
"bool";
"integer";
"object";
"type";
"let";
"and";
"open";
"float";
"timestamp";
"include";
"boolean";
"unit";
"switch";
"match";
"for";
"in";
"while";
"do";
"export";
"int";
"tagList";
"option";
"Option";
"Some";
"None";
"Result";
"Ok";
"Error";
"constraint";
"method";
"end";
"to";
"from";
"effect";
]
let uppercaseStartRe = Str.regexp "^\\([A-Z]*\\)\\(.*\\)$"
let uppercaseRe = Str.regexp "\\([A-Z][A-Z0-9]+[A-Z]\\|[A-Z]+\\)\\([^A-Z]*\\)"
let translateBadChars name =
(name
|> String.map ~f:(fun char ->
match[@ns.braces] char with
| 'A' .. 'Z' -> char
| 'a' .. 'z' -> char
| '0' .. '9' -> char
| _ -> '_'))
[@ns.braces]
let translateReserved (name : string) =
if StringSet.exists ~f:(fun word -> String.equal word name) reservedWords then name ^ "_"
else name
let stripLeadingNumbers name =
if String.length name = 0 then name
else (
match name.[0] with
| '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' -> {js|x|js} ^ name
| _ -> name)
let snakeCase name =
let start_pos = ref 0 in
let name_len = String.length name in
let components : string list ref = ref [] in
while !start_pos < name_len do
try
let next_pos = Str.search_forward uppercaseRe name !start_pos in
if not (Int.equal next_pos !start_pos) then begin
(*first section not uppercase - add first section as_is*)
let len = next_pos - !start_pos in
let group = String.unsafe_sub ~pos:!start_pos ~len name in
components := group :: !components;
start_pos := next_pos
end;
let upperpart = Str.matched_group 1 name in
let lowerpart = Str.matched_group 2 name in
if String.length upperpart > 1 then (
(* sequence of uppercase characters - convert all but one to their own group *)
let group_len = String.length upperpart - 1 in
let group = Str.string_before upperpart group_len |> String.lowercase in
components := group :: !components;
start_pos := !start_pos + group_len)
else (
(* one uppercase followed by some not-upper *)
let group_len = String.length lowerpart + 1 in
let group = String.lowercase upperpart ^ lowerpart in
components := group :: !components;
start_pos := !start_pos + group_len)
with Stdlib.Not_found ->
components := Str.string_after name !start_pos :: !components;
start_pos := name_len + 1
done;
!components |> List.rev |> String.concat ~sep:"_" |> stripLeadingNumbers |> translateReserved
let safeMemberName = snakeCase
let safeTypeName target =
(let name = symbolName target in
let namespace = symbolNamespace target in
match namespace with "smithy.api" -> safeMemberName ("Base" ^ name) | _ -> safeMemberName name)
[@ns.braces]
let safeFunctionName = safeTypeName
let camelCase name =
String.uppercase (String.sub name ~pos:0 ~len:1)
^ String.sub name ~pos:1 ~len:(String.length name - 1)
let safeConstructorName name = name |> symbolName |> camelCase
let variantReplaceRe = Str.regexp "-|#|:|\\.|/| |\\(|\\)|\\\\`"
let safeVariantName name =
(name
|> Str.global_replace variantReplaceRe "_"
|> String.substr_replace_all ~pattern:"*" ~with_:"Star"
|> String.split ~on:'_'
|> List.filter_map ~f:(fun x ->
(if String.length x > 0 then Some (camelCase x) else None) [@ns.ternary])
|> String.concat ~sep:"_")
[@ns.braces]