pub const PYTHON_KEYWORDS: &[&str] = &[
"False", "None", "True", "and", "as", "assert", "async", "await", "break", "class", "continue", "def", "del",
"elif", "else", "except", "finally", "for", "from", "global", "if", "import", "in", "is", "lambda", "nonlocal",
"not", "or", "pass", "raise", "return", "try", "type", "while", "with", "yield",
];
pub const PYTHON_STR_METHODS: &[&str] = &[
"capitalize",
"casefold",
"center",
"count",
"encode",
"endswith",
"expandtabs",
"find",
"format",
"format_map",
"index",
"isalnum",
"isalpha",
"isascii",
"isdecimal",
"isdigit",
"isidentifier",
"islower",
"isnumeric",
"isprintable",
"isspace",
"istitle",
"isupper",
"join",
"ljust",
"lower",
"lstrip",
"maketrans",
"partition",
"removeprefix",
"removesuffix",
"replace",
"rfind",
"rindex",
"rjust",
"rpartition",
"rsplit",
"rstrip",
"split",
"splitlines",
"startswith",
"strip",
"swapcase",
"title",
"translate",
"upper",
"zfill",
];
pub const JAVA_KEYWORDS: &[&str] = &[
"abstract",
"assert",
"boolean",
"break",
"byte",
"case",
"catch",
"char",
"class",
"const",
"continue",
"default",
"do",
"double",
"else",
"enum",
"extends",
"final",
"finally",
"float",
"for",
"goto",
"if",
"implements",
"import",
"instanceof",
"int",
"interface",
"long",
"native",
"new",
"package",
"private",
"protected",
"public",
"return",
"short",
"static",
"strictfp",
"super",
"switch",
"synchronized",
"this",
"throw",
"throws",
"transient",
"try",
"void",
"volatile",
"while",
];
pub const CSHARP_KEYWORDS: &[&str] = &[
"abstract",
"as",
"base",
"bool",
"break",
"byte",
"case",
"catch",
"char",
"checked",
"class",
"const",
"continue",
"decimal",
"default",
"delegate",
"do",
"double",
"else",
"enum",
"event",
"explicit",
"extern",
"false",
"finally",
"fixed",
"float",
"for",
"foreach",
"goto",
"if",
"implicit",
"in",
"int",
"interface",
"internal",
"is",
"lock",
"long",
"namespace",
"new",
"null",
"object",
"operator",
"out",
"override",
"params",
"private",
"protected",
"public",
"readonly",
"ref",
"return",
"sbyte",
"sealed",
"short",
"sizeof",
"stackalloc",
"static",
"string",
"struct",
"switch",
"this",
"throw",
"true",
"try",
"typeof",
"uint",
"ulong",
"unchecked",
"unsafe",
"ushort",
"using",
"virtual",
"void",
"volatile",
"while",
];
pub const PHP_KEYWORDS: &[&str] = &[
"abstract",
"and",
"as",
"break",
"callable",
"case",
"catch",
"class",
"clone",
"const",
"continue",
"declare",
"default",
"die",
"do",
"echo",
"else",
"elseif",
"empty",
"enddeclare",
"endfor",
"endforeach",
"endif",
"endswitch",
"endwhile",
"eval",
"exit",
"extends",
"final",
"finally",
"fn",
"for",
"foreach",
"function",
"global",
"goto",
"if",
"implements",
"include",
"instanceof",
"insteadof",
"interface",
"isset",
"list",
"match",
"namespace",
"new",
"or",
"print",
"private",
"protected",
"public",
"readonly",
"require",
"return",
"static",
"switch",
"throw",
"trait",
"try",
"unset",
"use",
"var",
"while",
"xor",
"yield",
];
pub const RUBY_KEYWORDS: &[&str] = &[
"__ENCODING__",
"__FILE__",
"__LINE__",
"BEGIN",
"END",
"alias",
"and",
"begin",
"break",
"case",
"class",
"def",
"defined?",
"do",
"else",
"elsif",
"end",
"ensure",
"false",
"for",
"if",
"in",
"module",
"next",
"nil",
"not",
"or",
"redo",
"rescue",
"retry",
"return",
"self",
"super",
"then",
"true",
"undef",
"unless",
"until",
"when",
"while",
"yield",
];
pub const ELIXIR_KEYWORDS: &[&str] = &[
"after", "and", "catch", "do", "else", "end", "false", "fn", "in", "nil", "not", "or", "rescue", "true", "when",
];
pub const GO_KEYWORDS: &[&str] = &[
"break",
"case",
"chan",
"const",
"continue",
"default",
"defer",
"else",
"fallthrough",
"for",
"func",
"go",
"goto",
"if",
"import",
"interface",
"map",
"package",
"range",
"return",
"select",
"struct",
"switch",
"type",
"var",
];
pub const JS_KEYWORDS: &[&str] = &[
"abstract",
"arguments",
"await",
"boolean",
"break",
"byte",
"case",
"catch",
"char",
"class",
"const",
"continue",
"debugger",
"default",
"delete",
"do",
"double",
"else",
"enum",
"eval",
"export",
"extends",
"false",
"final",
"finally",
"float",
"for",
"function",
"goto",
"if",
"implements",
"import",
"in",
"instanceof",
"int",
"interface",
"let",
"long",
"native",
"new",
"null",
"package",
"private",
"protected",
"public",
"return",
"short",
"static",
"super",
"switch",
"synchronized",
"this",
"throw",
"throws",
"transient",
"true",
"try",
"typeof",
"var",
"void",
"volatile",
"while",
"with",
"yield",
];
pub const R_KEYWORDS: &[&str] = &[
"FALSE", "Inf", "NA", "NaN", "NULL", "TRUE", "break", "else", "for", "function", "if", "in", "next", "repeat",
"return", "while",
];
pub const KOTLIN_KEYWORDS: &[&str] = &[
"as",
"break",
"class",
"continue",
"do",
"else",
"false",
"for",
"fun",
"if",
"in",
"interface",
"is",
"null",
"object",
"package",
"return",
"super",
"this",
"throw",
"true",
"try",
"typealias",
"typeof",
"val",
"var",
"when",
"while",
"by",
"init",
"constructor",
"field",
"value",
"where",
];
pub const SWIFT_KEYWORDS: &[&str] = &[
"associatedtype",
"class",
"deinit",
"enum",
"extension",
"fileprivate",
"func",
"import",
"init",
"inout",
"internal",
"let",
"open",
"operator",
"private",
"protocol",
"public",
"rethrows",
"static",
"struct",
"subscript",
"typealias",
"var",
"break",
"case",
"continue",
"default",
"defer",
"do",
"else",
"fallthrough",
"for",
"guard",
"if",
"in",
"repeat",
"return",
"switch",
"where",
"while",
"as",
"Any",
"catch",
"false",
"is",
"nil",
"super",
"self",
"Self",
"throw",
"throws",
"true",
"try",
"_",
];
pub const DART_KEYWORDS: &[&str] = &[
"abstract",
"as",
"assert",
"async",
"await",
"break",
"case",
"catch",
"class",
"const",
"continue",
"covariant",
"default",
"deferred",
"do",
"dynamic",
"else",
"enum",
"export",
"extends",
"extension",
"external",
"factory",
"false",
"final",
"finally",
"for",
"Function",
"get",
"hide",
"if",
"implements",
"import",
"in",
"interface",
"is",
"late",
"library",
"mixin",
"new",
"null",
"of",
"on",
"operator",
"part",
"required",
"rethrow",
"return",
"set",
"show",
"static",
"super",
"switch",
"sync",
"this",
"throw",
"true",
"try",
"typedef",
"var",
"void",
"when",
"while",
"with",
"yield",
];
pub const GLEAM_KEYWORDS: &[&str] = &[
"as",
"assert",
"auto",
"case",
"const",
"delegate",
"derive",
"echo",
"else",
"fn",
"if",
"implement",
"import",
"let",
"macro",
"opaque",
"panic",
"pub",
"test",
"todo",
"type",
"use",
];
pub const ZIG_KEYWORDS: &[&str] = &[
"addrspace",
"align",
"allowzero",
"and",
"anyframe",
"anytype",
"asm",
"async",
"await",
"break",
"callconv",
"catch",
"comptime",
"const",
"continue",
"defer",
"else",
"enum",
"errdefer",
"error",
"export",
"extern",
"fn",
"for",
"if",
"inline",
"linksection",
"noalias",
"noinline",
"nosuspend",
"or",
"orelse",
"packed",
"pub",
"resume",
"return",
"struct",
"suspend",
"switch",
"test",
"threadlocal",
"try",
"union",
"unreachable",
"usingnamespace",
"var",
"volatile",
"while",
];
pub const RUST_KEYWORDS: &[&str] = &[
"as", "break", "const", "continue", "crate", "else", "enum", "extern", "false", "fn", "for", "if", "impl", "in",
"let", "loop", "match", "mod", "move", "mut", "pub", "ref", "return", "self", "Self", "static", "struct", "super",
"trait", "true", "type", "unsafe", "use", "where", "while", "async", "await", "dyn",
"abstract", "become", "box", "do", "final", "macro", "override", "priv", "typeof", "unsized", "virtual", "yield",
"try",
];
pub fn rust_raw_ident_safe(name: &str) -> Option<String> {
if RUST_KEYWORDS.contains(&name) {
Some(format!("r#{name}"))
} else {
None
}
}
pub fn rust_raw_ident(name: &str) -> String {
rust_raw_ident_safe(name).unwrap_or_else(|| name.to_string())
}
pub fn is_valid_rust_ident_chars(name: &str) -> bool {
if name.is_empty() {
return false;
}
let mut chars = name.chars();
let first = chars.next().expect("non-empty string has a first char");
if !first.is_alphabetic() && first != '_' {
return false;
}
chars.all(|c| c.is_alphanumeric() || c == '_')
}
pub fn python_safe_name(name: &str) -> Option<String> {
if PYTHON_KEYWORDS.contains(&name) {
Some(format!("{name}_"))
} else {
None
}
}
pub fn python_ident(name: &str) -> String {
python_safe_name(name).unwrap_or_else(|| name.to_string())
}
pub fn python_str_enum_safe_name(name: &str) -> Option<String> {
if PYTHON_KEYWORDS.contains(&name) || PYTHON_STR_METHODS.contains(&name) {
Some(format!("{name}_"))
} else {
None
}
}
pub fn python_str_enum_ident(name: &str) -> String {
python_str_enum_safe_name(name).unwrap_or_else(|| name.to_string())
}
pub fn kotlin_safe_name(name: &str) -> Option<String> {
if KOTLIN_KEYWORDS.contains(&name) {
Some(format!("{name}_"))
} else {
None
}
}
pub fn kotlin_ident(name: &str) -> String {
kotlin_safe_name(name).unwrap_or_else(|| name.to_string())
}
pub fn swift_safe_name(name: &str) -> Option<String> {
if SWIFT_KEYWORDS.contains(&name) {
Some(format!("{name}_"))
} else {
None
}
}
pub fn swift_ident(name: &str) -> String {
swift_safe_name(name).unwrap_or_else(|| name.to_string())
}
pub fn swift_case_safe_name(name: &str) -> Option<String> {
if SWIFT_KEYWORDS.contains(&name) {
Some(format!("`{name}`"))
} else {
None
}
}
pub fn swift_case_ident(name: &str) -> String {
swift_case_safe_name(name).unwrap_or_else(|| name.to_string())
}
pub fn dart_safe_name(name: &str) -> Option<String> {
if DART_KEYWORDS.contains(&name) {
Some(format!("{name}_"))
} else {
None
}
}
pub fn dart_ident(name: &str) -> String {
dart_safe_name(name).unwrap_or_else(|| name.to_string())
}
pub fn gleam_safe_name(name: &str) -> Option<String> {
if GLEAM_KEYWORDS.contains(&name) {
Some(format!("{name}_"))
} else {
None
}
}
pub fn gleam_ident(name: &str) -> String {
gleam_safe_name(name).unwrap_or_else(|| name.to_string())
}
pub fn zig_safe_name(name: &str) -> Option<String> {
if ZIG_KEYWORDS.contains(&name) {
Some(format!("{name}_"))
} else {
None
}
}
pub fn zig_ident(name: &str) -> String {
let mut sanitized = String::with_capacity(name.len() + 1);
for ch in name.chars() {
if ch.is_ascii_alphanumeric() || ch == '_' {
sanitized.push(ch);
} else {
sanitized.push('_');
}
}
if sanitized.chars().next().is_some_and(|ch| ch.is_ascii_digit()) {
sanitized.insert(0, '_');
}
zig_safe_name(&sanitized).unwrap_or(sanitized)
}
#[cfg(test)]
mod tests;