From 70bb7e0e1d7231928b51db444cef3fbd231ca7f6 Mon Sep 17 00:00:00 2001 From: primoly <168267431+primoly@users.noreply.github.com> Date: Sun, 28 Apr 2024 10:20:10 +0200 Subject: [PATCH 1/9] Fix C and C++ keywords with underscores collisions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert to snake case *before* checking for keyword collisions, so C and C++ keywords with underscores will be “escaped” as well. --- crates/c/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/c/src/lib.rs b/crates/c/src/lib.rs index 23f91bc3d..8e68db96c 100644 --- a/crates/c/src/lib.rs +++ b/crates/c/src/lib.rs @@ -3140,7 +3140,8 @@ pub fn is_arg_by_pointer(resolve: &Resolve, ty: &Type) -> bool { } pub fn to_c_ident(name: &str) -> String { - match name { + let ident = name.to_snake_case(); + match ident.as_str() { // Escape C and C++ keywords. // Source: https://en.cppreference.com/w/cpp/keyword "alignas" => "alignas_".into(), @@ -3245,6 +3246,6 @@ pub fn to_c_ident(name: &str) -> String { // variable names for option and result flattening. "ret" => "ret_".into(), "err" => "err_".into(), - s => s.to_snake_case(), + _ => ident, } } From 48cf84e7c3ca89abe56866dcd40300ae6e34cc20 Mon Sep 17 00:00:00 2001 From: primoly <168267431+primoly@users.noreply.github.com> Date: Sun, 28 Apr 2024 19:52:12 +0200 Subject: [PATCH 2/9] Escape C# keywords --- crates/csharp/src/lib.rs | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/crates/csharp/src/lib.rs b/crates/csharp/src/lib.rs index 6f71610ce..822adb0e8 100644 --- a/crates/csharp/src/lib.rs +++ b/crates/csharp/src/lib.rs @@ -2584,20 +2584,27 @@ trait ToCSharpIdent: ToOwned { impl ToCSharpIdent for str { fn to_csharp_ident(&self) -> String { - // Escape C# keywords - // Source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ - - //TODO: Repace with actual keywords - match self { - "abstract" | "continue" | "for" | "new" | "switch" | "assert" | "default" | "goto" - | "namespace" | "synchronized" | "boolean" | "do" | "if" | "private" | "this" - | "break" | "double" | "implements" | "protected" | "throw" | "byte" | "else" - | "import" | "public" | "throws" | "case" | "enum" | "instanceof" | "return" - | "transient" | "catch" | "extends" | "int" | "short" | "try" | "char" | "final" - | "interface" | "static" | "void" | "class" | "finally" | "long" | "strictfp" - | "volatile" | "const" | "float" | "super" | "while" | "extern" | "sizeof" | "type" - | "struct" => format!("@{self}"), - _ => self.to_lower_camel_case(), + let ident = self.to_lower_camel_case(); + match ident { + // Escape C# keywords + // Source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ + "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" | "add" | "and" | "alias" | "ascending" | "args" | "async" | "await" + | "by" | "descending" | "dynamic" | "equals" | "file" | "from" | "get" | "global" + | "group" | "init" | "into" | "join" | "let" | "managed" | "nameof" | "nint" + | "not" | "notnull" | "nuint" | "on" | "or" | "orderby" | "partial" | "record" + | "remove" | "required" | "scoped" | "select" | "set" | "unmanaged" | "value" + | "var" | "when" | "where" | "with" | "yield" => format!("@{ident}"), + _ => ident, } } } From c9a02b83c8b397b5d65a6d8adfbfe4f59296c888 Mon Sep 17 00:00:00 2001 From: primoly <168267431+primoly@users.noreply.github.com> Date: Sun, 28 Apr 2024 21:16:35 +0200 Subject: [PATCH 3/9] Update lib.rs --- crates/csharp/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/csharp/src/lib.rs b/crates/csharp/src/lib.rs index 822adb0e8..7f148e40d 100644 --- a/crates/csharp/src/lib.rs +++ b/crates/csharp/src/lib.rs @@ -2585,7 +2585,7 @@ trait ToCSharpIdent: ToOwned { impl ToCSharpIdent for str { fn to_csharp_ident(&self) -> String { let ident = self.to_lower_camel_case(); - match ident { + match ident.as_str() { // Escape C# keywords // Source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ "abstract" | "as" | "base" | "bool" | "break" | "byte" | "case" | "catch" | "char" From 6002e4b79e20c6eea4f493c0f3ef801fd056a6f8 Mon Sep 17 00:00:00 2001 From: primoly <168267431+primoly@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:28:16 +0200 Subject: [PATCH 4/9] Rust convert before check --- crates/rust/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/rust/src/lib.rs b/crates/rust/src/lib.rs index f57202614..4b85899ab 100644 --- a/crates/rust/src/lib.rs +++ b/crates/rust/src/lib.rs @@ -1171,7 +1171,8 @@ struct FnSig { } pub fn to_rust_ident(name: &str) -> String { - match name { + let ident = name.to_snake_case(); + match ident.as_str() { // Escape Rust keywords. // Source: https://doc.rust-lang.org/reference/keywords.html "as" => "as_".into(), @@ -1224,7 +1225,7 @@ pub fn to_rust_ident(name: &str) -> String { "virtual" => "virtual_".into(), "yield" => "yield_".into(), "try" => "try_".into(), - s => s.to_snake_case(), + _ => ident, } } From b840296dbfef59258cb4c13cada90c10cae9080d Mon Sep 17 00:00:00 2001 From: primoly <168267431+primoly@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:32:01 +0200 Subject: [PATCH 5/9] Java convert before check --- crates/teavm-java/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/teavm-java/src/lib.rs b/crates/teavm-java/src/lib.rs index adb14a5db..f80d2fade 100644 --- a/crates/teavm-java/src/lib.rs +++ b/crates/teavm-java/src/lib.rs @@ -2273,17 +2273,18 @@ trait ToJavaIdent: ToOwned { impl ToJavaIdent for str { fn to_java_ident(&self) -> String { - // Escape Java keywords - // Source: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html - match self { + let ident = self.to_lower_camel_case(); + match ident.as_str() { + // Escape Java keywords + // Source: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html "abstract" | "continue" | "for" | "new" | "switch" | "assert" | "default" | "goto" | "package" | "synchronized" | "boolean" | "do" | "if" | "private" | "this" | "break" | "double" | "implements" | "protected" | "throw" | "byte" | "else" | "import" | "public" | "throws" | "case" | "enum" | "instanceof" | "return" | "transient" | "catch" | "extends" | "int" | "short" | "try" | "char" | "final" | "interface" | "static" | "void" | "class" | "finally" | "long" | "strictfp" - | "volatile" | "const" | "float" | "native" | "super" | "while" => format!("{self}_"), - _ => self.to_lower_camel_case(), + | "volatile" | "const" | "float" | "native" | "super" | "while" => format!("{ident}_"), + _ => ident, } } } From 0f1cc245641d4c1d447532d55ee69c16344c6ed2 Mon Sep 17 00:00:00 2001 From: primoly <168267431+primoly@users.noreply.github.com> Date: Mon, 29 Apr 2024 22:41:06 +0200 Subject: [PATCH 6/9] Create keywords-uppercase.wit --- tests/codegen/keywords-uppercase.wit | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/codegen/keywords-uppercase.wit diff --git a/tests/codegen/keywords-uppercase.wit b/tests/codegen/keywords-uppercase.wit new file mode 100644 index 000000000..4b6479344 --- /dev/null +++ b/tests/codegen/keywords-uppercase.wit @@ -0,0 +1,15 @@ +package foo:foo; + +interface keywords-uppercase { + record CONST { + BREAK: u8, + ELSE: u8, + co-RETURN: u8, + } + WHILE: func(ENUM: CONST) -> option; +} + +world the-world { + import keywords-uppercase; + export keywords-uppercase; +} From 3c7faf4652dc2ec610bd14da473a1e819501d638 Mon Sep 17 00:00:00 2001 From: primoly <168267431+primoly@users.noreply.github.com> Date: Tue, 30 Apr 2024 18:50:41 +0200 Subject: [PATCH 7/9] better test case --- tests/codegen/keywords-uppercase.wit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen/keywords-uppercase.wit b/tests/codegen/keywords-uppercase.wit index 4b6479344..77824758b 100644 --- a/tests/codegen/keywords-uppercase.wit +++ b/tests/codegen/keywords-uppercase.wit @@ -4,7 +4,7 @@ interface keywords-uppercase { record CONST { BREAK: u8, ELSE: u8, - co-RETURN: u8, + CONST-CAST: u8, } WHILE: func(ENUM: CONST) -> option; } From 2cbb257816e9ba4b27711aacfdb5e09b1db6189e Mon Sep 17 00:00:00 2001 From: primoly <168267431+primoly@users.noreply.github.com> Date: Thu, 2 May 2024 21:50:21 +0200 Subject: [PATCH 8/9] Ignore uppercase keywords test in Go --- crates/go/tests/codegen.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/go/tests/codegen.rs b/crates/go/tests/codegen.rs index 9a7d8b837..4d32d3f3f 100644 --- a/crates/go/tests/codegen.rs +++ b/crates/go/tests/codegen.rs @@ -8,6 +8,7 @@ use heck::*; macro_rules! codegen_test { (issue668 $name:tt $test:tt) => {}; (multiversion $name:tt $test:tt) => {}; + (keywords_uppercase $name:tt $test:tt) => {}; ($id:ident $name:tt $test:tt) => { #[test] fn $id() { From 7347680be93e54e3fe769f52df18a928ae801c72 Mon Sep 17 00:00:00 2001 From: primoly <168267431+primoly@users.noreply.github.com> Date: Tue, 7 May 2024 08:44:22 +0200 Subject: [PATCH 9/9] refactoring anticipating #927 --- crates/rust/src/lib.rs | 56 +++++------------------------------------- 1 file changed, 6 insertions(+), 50 deletions(-) diff --git a/crates/rust/src/lib.rs b/crates/rust/src/lib.rs index 4b85899ab..4d293308c 100644 --- a/crates/rust/src/lib.rs +++ b/crates/rust/src/lib.rs @@ -1175,56 +1175,12 @@ pub fn to_rust_ident(name: &str) -> String { match ident.as_str() { // Escape Rust keywords. // Source: https://doc.rust-lang.org/reference/keywords.html - "as" => "as_".into(), - "break" => "break_".into(), - "const" => "const_".into(), - "continue" => "continue_".into(), - "crate" => "crate_".into(), - "else" => "else_".into(), - "enum" => "enum_".into(), - "extern" => "extern_".into(), - "false" => "false_".into(), - "fn" => "fn_".into(), - "for" => "for_".into(), - "if" => "if_".into(), - "impl" => "impl_".into(), - "in" => "in_".into(), - "let" => "let_".into(), - "loop" => "loop_".into(), - "match" => "match_".into(), - "mod" => "mod_".into(), - "move" => "move_".into(), - "mut" => "mut_".into(), - "pub" => "pub_".into(), - "ref" => "ref_".into(), - "return" => "return_".into(), - "self" => "self_".into(), - "static" => "static_".into(), - "struct" => "struct_".into(), - "super" => "super_".into(), - "trait" => "trait_".into(), - "true" => "true_".into(), - "type" => "type_".into(), - "unsafe" => "unsafe_".into(), - "use" => "use_".into(), - "where" => "where_".into(), - "while" => "while_".into(), - "async" => "async_".into(), - "await" => "await_".into(), - "dyn" => "dyn_".into(), - "abstract" => "abstract_".into(), - "become" => "become_".into(), - "box" => "box_".into(), - "do" => "do_".into(), - "final" => "final_".into(), - "macro" => "macro_".into(), - "override" => "override_".into(), - "priv" => "priv_".into(), - "typeof" => "typeof_".into(), - "unsized" => "unsized_".into(), - "virtual" => "virtual_".into(), - "yield" => "yield_".into(), - "try" => "try_".into(), + "as" | "break" | "const" | "continue" | "crate" | "else" | "enum" | "extern" | "false" + | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "match" | "mod" | "move" + | "mut" | "pub" | "ref" | "return" | "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" => format!("{ident}_"), _ => ident, } }