1pub const PYTHON_KEYWORDS: &[&str] = &[
19 "False", "None", "True", "and", "as", "assert", "async", "await", "break", "class", "continue", "def", "del",
20 "elif", "else", "except", "finally", "for", "from", "global", "if", "import", "in", "is", "lambda", "nonlocal",
21 "not", "or", "pass", "raise", "return", "try", "type", "while", "with", "yield",
22];
23
24pub const JAVA_KEYWORDS: &[&str] = &[
26 "abstract",
27 "assert",
28 "boolean",
29 "break",
30 "byte",
31 "case",
32 "catch",
33 "char",
34 "class",
35 "const",
36 "continue",
37 "default",
38 "do",
39 "double",
40 "else",
41 "enum",
42 "extends",
43 "final",
44 "finally",
45 "float",
46 "for",
47 "goto",
48 "if",
49 "implements",
50 "import",
51 "instanceof",
52 "int",
53 "interface",
54 "long",
55 "native",
56 "new",
57 "package",
58 "private",
59 "protected",
60 "public",
61 "return",
62 "short",
63 "static",
64 "strictfp",
65 "super",
66 "switch",
67 "synchronized",
68 "this",
69 "throw",
70 "throws",
71 "transient",
72 "try",
73 "void",
74 "volatile",
75 "while",
76];
77
78pub const CSHARP_KEYWORDS: &[&str] = &[
80 "abstract",
81 "as",
82 "base",
83 "bool",
84 "break",
85 "byte",
86 "case",
87 "catch",
88 "char",
89 "checked",
90 "class",
91 "const",
92 "continue",
93 "decimal",
94 "default",
95 "delegate",
96 "do",
97 "double",
98 "else",
99 "enum",
100 "event",
101 "explicit",
102 "extern",
103 "false",
104 "finally",
105 "fixed",
106 "float",
107 "for",
108 "foreach",
109 "goto",
110 "if",
111 "implicit",
112 "in",
113 "int",
114 "interface",
115 "internal",
116 "is",
117 "lock",
118 "long",
119 "namespace",
120 "new",
121 "null",
122 "object",
123 "operator",
124 "out",
125 "override",
126 "params",
127 "private",
128 "protected",
129 "public",
130 "readonly",
131 "ref",
132 "return",
133 "sbyte",
134 "sealed",
135 "short",
136 "sizeof",
137 "stackalloc",
138 "static",
139 "string",
140 "struct",
141 "switch",
142 "this",
143 "throw",
144 "true",
145 "try",
146 "typeof",
147 "uint",
148 "ulong",
149 "unchecked",
150 "unsafe",
151 "ushort",
152 "using",
153 "virtual",
154 "void",
155 "volatile",
156 "while",
157];
158
159pub const PHP_KEYWORDS: &[&str] = &[
161 "abstract",
162 "and",
163 "as",
164 "break",
165 "callable",
166 "case",
167 "catch",
168 "class",
169 "clone",
170 "const",
171 "continue",
172 "declare",
173 "default",
174 "die",
175 "do",
176 "echo",
177 "else",
178 "elseif",
179 "empty",
180 "enddeclare",
181 "endfor",
182 "endforeach",
183 "endif",
184 "endswitch",
185 "endwhile",
186 "eval",
187 "exit",
188 "extends",
189 "final",
190 "finally",
191 "fn",
192 "for",
193 "foreach",
194 "function",
195 "global",
196 "goto",
197 "if",
198 "implements",
199 "include",
200 "instanceof",
201 "insteadof",
202 "interface",
203 "isset",
204 "list",
205 "match",
206 "namespace",
207 "new",
208 "or",
209 "print",
210 "private",
211 "protected",
212 "public",
213 "readonly",
214 "require",
215 "return",
216 "static",
217 "switch",
218 "throw",
219 "trait",
220 "try",
221 "unset",
222 "use",
223 "var",
224 "while",
225 "xor",
226 "yield",
227];
228
229pub const RUBY_KEYWORDS: &[&str] = &[
231 "__ENCODING__",
232 "__FILE__",
233 "__LINE__",
234 "BEGIN",
235 "END",
236 "alias",
237 "and",
238 "begin",
239 "break",
240 "case",
241 "class",
242 "def",
243 "defined?",
244 "do",
245 "else",
246 "elsif",
247 "end",
248 "ensure",
249 "false",
250 "for",
251 "if",
252 "in",
253 "module",
254 "next",
255 "nil",
256 "not",
257 "or",
258 "redo",
259 "rescue",
260 "retry",
261 "return",
262 "self",
263 "super",
264 "then",
265 "true",
266 "undef",
267 "unless",
268 "until",
269 "when",
270 "while",
271 "yield",
272];
273
274pub const ELIXIR_KEYWORDS: &[&str] = &[
276 "after", "and", "catch", "do", "else", "end", "false", "fn", "in", "nil", "not", "or", "rescue", "true", "when",
277];
278
279pub const GO_KEYWORDS: &[&str] = &[
281 "break",
282 "case",
283 "chan",
284 "const",
285 "continue",
286 "default",
287 "defer",
288 "else",
289 "fallthrough",
290 "for",
291 "func",
292 "go",
293 "goto",
294 "if",
295 "import",
296 "interface",
297 "map",
298 "package",
299 "range",
300 "return",
301 "select",
302 "struct",
303 "switch",
304 "type",
305 "var",
306];
307
308pub const JS_KEYWORDS: &[&str] = &[
310 "abstract",
311 "arguments",
312 "await",
313 "boolean",
314 "break",
315 "byte",
316 "case",
317 "catch",
318 "char",
319 "class",
320 "const",
321 "continue",
322 "debugger",
323 "default",
324 "delete",
325 "do",
326 "double",
327 "else",
328 "enum",
329 "eval",
330 "export",
331 "extends",
332 "false",
333 "final",
334 "finally",
335 "float",
336 "for",
337 "function",
338 "goto",
339 "if",
340 "implements",
341 "import",
342 "in",
343 "instanceof",
344 "int",
345 "interface",
346 "let",
347 "long",
348 "native",
349 "new",
350 "null",
351 "package",
352 "private",
353 "protected",
354 "public",
355 "return",
356 "short",
357 "static",
358 "super",
359 "switch",
360 "synchronized",
361 "this",
362 "throw",
363 "throws",
364 "transient",
365 "true",
366 "try",
367 "typeof",
368 "var",
369 "void",
370 "volatile",
371 "while",
372 "with",
373 "yield",
374];
375
376pub const R_KEYWORDS: &[&str] = &[
378 "FALSE", "Inf", "NA", "NaN", "NULL", "TRUE", "break", "else", "for", "function", "if", "in", "next", "repeat",
379 "return", "while",
380];
381
382pub const KOTLIN_KEYWORDS: &[&str] = &[
384 "as",
385 "break",
386 "class",
387 "continue",
388 "do",
389 "else",
390 "false",
391 "for",
392 "fun",
393 "if",
394 "in",
395 "interface",
396 "is",
397 "null",
398 "object",
399 "package",
400 "return",
401 "super",
402 "this",
403 "throw",
404 "true",
405 "try",
406 "typealias",
407 "typeof",
408 "val",
409 "var",
410 "when",
411 "while",
412 "by",
414 "init",
415 "constructor",
416 "field",
417 "value",
418 "where",
419];
420
421pub const SWIFT_KEYWORDS: &[&str] = &[
423 "associatedtype",
424 "class",
425 "deinit",
426 "enum",
427 "extension",
428 "fileprivate",
429 "func",
430 "import",
431 "init",
432 "inout",
433 "internal",
434 "let",
435 "open",
436 "operator",
437 "private",
438 "protocol",
439 "public",
440 "rethrows",
441 "static",
442 "struct",
443 "subscript",
444 "typealias",
445 "var",
446 "break",
447 "case",
448 "continue",
449 "default",
450 "defer",
451 "do",
452 "else",
453 "fallthrough",
454 "for",
455 "guard",
456 "if",
457 "in",
458 "repeat",
459 "return",
460 "switch",
461 "where",
462 "while",
463 "as",
464 "Any",
465 "catch",
466 "false",
467 "is",
468 "nil",
469 "super",
470 "self",
471 "Self",
472 "throw",
473 "throws",
474 "true",
475 "try",
476 "_",
477];
478
479pub const DART_KEYWORDS: &[&str] = &[
481 "abstract",
482 "as",
483 "assert",
484 "async",
485 "await",
486 "break",
487 "case",
488 "catch",
489 "class",
490 "const",
491 "continue",
492 "covariant",
493 "default",
494 "deferred",
495 "do",
496 "dynamic",
497 "else",
498 "enum",
499 "export",
500 "extends",
501 "extension",
502 "external",
503 "factory",
504 "false",
505 "final",
506 "finally",
507 "for",
508 "Function",
509 "get",
510 "hide",
511 "if",
512 "implements",
513 "import",
514 "in",
515 "interface",
516 "is",
517 "late",
518 "library",
519 "mixin",
520 "new",
521 "null",
522 "of",
523 "on",
524 "operator",
525 "part",
526 "required",
527 "rethrow",
528 "return",
529 "set",
530 "show",
531 "static",
532 "super",
533 "switch",
534 "sync",
535 "this",
536 "throw",
537 "true",
538 "try",
539 "typedef",
540 "var",
541 "void",
542 "when",
543 "while",
544 "with",
545 "yield",
546];
547
548pub const GLEAM_KEYWORDS: &[&str] = &[
550 "as",
551 "assert",
552 "auto",
553 "case",
554 "const",
555 "delegate",
556 "derive",
557 "echo",
558 "else",
559 "fn",
560 "if",
561 "implement",
562 "import",
563 "let",
564 "macro",
565 "opaque",
566 "panic",
567 "pub",
568 "test",
569 "todo",
570 "type",
571 "use",
572];
573
574pub const ZIG_KEYWORDS: &[&str] = &[
576 "addrspace",
577 "align",
578 "allowzero",
579 "and",
580 "anyframe",
581 "anytype",
582 "asm",
583 "async",
584 "await",
585 "break",
586 "callconv",
587 "catch",
588 "comptime",
589 "const",
590 "continue",
591 "defer",
592 "else",
593 "enum",
594 "errdefer",
595 "error",
596 "export",
597 "extern",
598 "fn",
599 "for",
600 "if",
601 "inline",
602 "linksection",
603 "noalias",
604 "noinline",
605 "nosuspend",
606 "or",
607 "orelse",
608 "packed",
609 "pub",
610 "resume",
611 "return",
612 "struct",
613 "suspend",
614 "switch",
615 "test",
616 "threadlocal",
617 "try",
618 "union",
619 "unreachable",
620 "usingnamespace",
621 "var",
622 "volatile",
623 "while",
624];
625
626pub fn python_safe_name(name: &str) -> Option<String> {
634 if PYTHON_KEYWORDS.contains(&name) {
635 Some(format!("{name}_"))
636 } else {
637 None
638 }
639}
640
641pub fn python_ident(name: &str) -> String {
644 python_safe_name(name).unwrap_or_else(|| name.to_string())
645}
646
647pub fn kotlin_safe_name(name: &str) -> Option<String> {
649 if KOTLIN_KEYWORDS.contains(&name) {
650 Some(format!("{name}_"))
651 } else {
652 None
653 }
654}
655
656pub fn kotlin_ident(name: &str) -> String {
658 kotlin_safe_name(name).unwrap_or_else(|| name.to_string())
659}
660
661pub fn swift_safe_name(name: &str) -> Option<String> {
663 if SWIFT_KEYWORDS.contains(&name) {
664 Some(format!("{name}_"))
665 } else {
666 None
667 }
668}
669
670pub fn swift_ident(name: &str) -> String {
672 swift_safe_name(name).unwrap_or_else(|| name.to_string())
673}
674
675pub fn swift_case_safe_name(name: &str) -> Option<String> {
684 if SWIFT_KEYWORDS.contains(&name) {
685 Some(format!("`{name}`"))
686 } else {
687 None
688 }
689}
690
691pub fn swift_case_ident(name: &str) -> String {
698 swift_case_safe_name(name).unwrap_or_else(|| name.to_string())
699}
700
701pub fn dart_safe_name(name: &str) -> Option<String> {
703 if DART_KEYWORDS.contains(&name) {
704 Some(format!("{name}_"))
705 } else {
706 None
707 }
708}
709
710pub fn dart_ident(name: &str) -> String {
712 dart_safe_name(name).unwrap_or_else(|| name.to_string())
713}
714
715pub fn gleam_safe_name(name: &str) -> Option<String> {
717 if GLEAM_KEYWORDS.contains(&name) {
718 Some(format!("{name}_"))
719 } else {
720 None
721 }
722}
723
724pub fn gleam_ident(name: &str) -> String {
726 gleam_safe_name(name).unwrap_or_else(|| name.to_string())
727}
728
729pub fn zig_safe_name(name: &str) -> Option<String> {
731 if ZIG_KEYWORDS.contains(&name) {
732 Some(format!("{name}_"))
733 } else {
734 None
735 }
736}
737
738pub fn zig_ident(name: &str) -> String {
747 let mut sanitized = String::with_capacity(name.len() + 1);
748 for ch in name.chars() {
749 if ch.is_ascii_alphanumeric() || ch == '_' {
750 sanitized.push(ch);
751 } else {
752 sanitized.push('_');
753 }
754 }
755 if sanitized.chars().next().is_some_and(|ch| ch.is_ascii_digit()) {
756 sanitized.insert(0, '_');
757 }
758 zig_safe_name(&sanitized).unwrap_or(sanitized)
759}
760
761#[cfg(test)]
762mod tests {
763 use super::*;
764
765 #[test]
766 fn python_class_is_reserved() {
767 assert_eq!(python_safe_name("class"), Some("class_".to_string()));
768 }
769
770 #[test]
771 fn python_ordinary_name_is_none() {
772 assert_eq!(python_safe_name("layout_class"), None);
773 }
774
775 #[test]
776 fn python_ident_reserved() {
777 assert_eq!(python_ident("class"), "class_");
778 }
779
780 #[test]
781 fn python_ident_ordinary() {
782 assert_eq!(python_ident("layout_class"), "layout_class");
783 }
784
785 #[test]
786 fn kotlin_class_is_reserved() {
787 assert_eq!(kotlin_safe_name("class"), Some("class_".to_string()));
788 assert_eq!(kotlin_safe_name("fun"), Some("fun_".to_string()));
789 assert_eq!(kotlin_safe_name("ordinary"), None);
790 assert_eq!(kotlin_ident("typealias"), "typealias_");
791 }
792
793 #[test]
794 fn swift_init_is_reserved() {
795 assert_eq!(swift_safe_name("init"), Some("init_".to_string()));
796 assert_eq!(swift_safe_name("Self"), Some("Self_".to_string()));
797 assert_eq!(swift_safe_name("normal"), None);
798 assert_eq!(swift_ident("protocol"), "protocol_");
799 }
800
801 #[test]
802 fn swift_case_ident_backtick_escapes_reserved_keywords() {
803 assert_eq!(swift_case_ident("default"), "`default`");
809 assert_eq!(swift_case_ident("protocol"), "`protocol`");
810 assert_eq!(swift_case_ident("init"), "`init`");
811 assert_eq!(swift_case_ident("Self"), "`Self`");
812 assert_eq!(swift_case_ident("Any"), "`Any`");
813 assert_eq!(swift_case_ident("class"), "`class`");
814 assert_eq!(swift_case_ident("inout"), "`inout`");
815 assert_eq!(swift_case_ident("rethrows"), "`rethrows`");
816 assert_eq!(swift_case_ident("gitHub"), "gitHub");
818 assert_eq!(swift_case_ident("normal"), "normal");
819 assert_eq!(swift_case_ident("dracula"), "dracula");
820 }
821
822 #[test]
823 fn swift_case_safe_name_returns_some_for_reserved() {
824 assert_eq!(swift_case_safe_name("default"), Some("`default`".to_string()));
825 assert_eq!(swift_case_safe_name("normal"), None);
826 }
827
828 #[test]
829 fn dart_async_is_reserved() {
830 assert_eq!(dart_safe_name("async"), Some("async_".to_string()));
831 assert_eq!(dart_safe_name("late"), Some("late_".to_string()));
832 assert_eq!(dart_safe_name("normal"), None);
833 assert_eq!(dart_ident("required"), "required_");
834 }
835
836 #[test]
837 fn gleam_pub_is_reserved() {
838 assert_eq!(gleam_safe_name("pub"), Some("pub_".to_string()));
839 assert_eq!(gleam_safe_name("opaque"), Some("opaque_".to_string()));
840 assert_eq!(gleam_safe_name("normal"), None);
841 assert_eq!(gleam_ident("type"), "type_");
842 }
843
844 #[test]
845 fn zig_comptime_is_reserved() {
846 assert_eq!(zig_safe_name("comptime"), Some("comptime_".to_string()));
847 assert_eq!(zig_safe_name("errdefer"), Some("errdefer_".to_string()));
848 assert_eq!(zig_safe_name("normal"), None);
849 assert_eq!(zig_ident("usingnamespace"), "usingnamespace_");
850 }
851
852 #[test]
853 fn python_keywords_covers_common_cases() {
854 for kw in &[
855 "def", "return", "yield", "pass", "import", "from", "type", "None", "True", "False",
856 ] {
857 assert!(
858 python_safe_name(kw).is_some(),
859 "expected {kw:?} to be a Python reserved keyword"
860 );
861 }
862 }
863}