From 19a572b72195c54814ae0755e09876b65089f3f7 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 4 Oct 2021 23:30:20 +0800 Subject: [PATCH 1/4] Escape rust keywords with `r#` raw identifier --- sea-orm-macros/src/derives/active_model.rs | 10 +-- sea-orm-macros/src/derives/entity_model.rs | 12 ++-- sea-orm-macros/src/derives/model.rs | 13 ++-- sea-orm-macros/src/util.rs | 40 ++++++++++++ src/tests_cfg/mod.rs | 2 + src/tests_cfg/rust_keyword.rs | 71 ++++++++++++++++++++++ 6 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 src/tests_cfg/rust_keyword.rs diff --git a/sea-orm-macros/src/derives/active_model.rs b/sea-orm-macros/src/derives/active_model.rs index 2227f09bd..85bdcb697 100644 --- a/sea-orm-macros/src/derives/active_model.rs +++ b/sea-orm-macros/src/derives/active_model.rs @@ -1,4 +1,4 @@ -use crate::util::field_not_ignored; +use crate::util::{escape_rust_keyword, field_not_ignored, trim_starting_raw_identifier}; use heck::CamelCase; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote, quote_spanned}; @@ -29,10 +29,10 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result) -> syn::Result { // if #[sea_orm(table_name = "foo", schema_name = "bar")] specified, create Entity struct let mut table_name = None; @@ -60,8 +60,10 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res if let Fields::Named(fields) = item_struct.fields { for field in fields.named { if let Some(ident) = &field.ident { - let mut field_name = - Ident::new(&ident.to_string().to_case(Case::Pascal), Span::call_site()); + let mut field_name = Ident::new( + &trim_starting_raw_identifier(&ident).to_case(Case::Pascal), + Span::call_site(), + ); let mut nullable = false; let mut default_value = None; @@ -168,6 +170,8 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res field_name = enum_name; } + field_name = Ident::new(&escape_rust_keyword(field_name), Span::call_site()); + if ignore { continue; } else { diff --git a/sea-orm-macros/src/derives/model.rs b/sea-orm-macros/src/derives/model.rs index a43b487f9..29a597b90 100644 --- a/sea-orm-macros/src/derives/model.rs +++ b/sea-orm-macros/src/derives/model.rs @@ -1,4 +1,7 @@ -use crate::{attributes::derive_attr, util::field_not_ignored}; +use crate::{ + attributes::derive_attr, + util::{escape_rust_keyword, field_not_ignored, trim_starting_raw_identifier}, +}; use heck::CamelCase; use proc_macro2::TokenStream; use quote::{format_ident, quote, quote_spanned}; @@ -43,10 +46,10 @@ impl DeriveModel { let column_idents = fields .iter() .map(|field| { - let mut ident = format_ident!( - "{}", - field.ident.as_ref().unwrap().to_string().to_camel_case() - ); + let ident = field.ident.as_ref().unwrap().to_string(); + let ident = trim_starting_raw_identifier(ident).to_camel_case(); + let ident = escape_rust_keyword(ident); + let mut ident = format_ident!("{}", &ident); for attr in field.attrs.iter() { if let Some(ident) = attr.path.get_ident() { if ident != "sea_orm" { diff --git a/sea-orm-macros/src/util.rs b/sea-orm-macros/src/util.rs index 7dda10872..8929e9e8e 100644 --- a/sea-orm-macros/src/util.rs +++ b/sea-orm-macros/src/util.rs @@ -24,3 +24,43 @@ pub(crate) fn field_not_ignored(field: &Field) -> bool { } true } + +pub(crate) fn trim_starting_raw_identifier(string: T) -> String +where + T: ToString, +{ + string + .to_string() + .trim_start_matches(RAW_IDENTIFIER) + .to_string() +} + +pub(crate) fn escape_rust_keyword(string: T) -> String +where + T: ToString, +{ + let string = string.to_string(); + if is_rust_keyword(&string) { + format!("r#{}", string) + } else { + string + } +} + +pub(crate) fn is_rust_keyword(string: T) -> bool +where + T: ToString, +{ + let string = string.to_string(); + RUST_KEYWORDS.iter().any(|s| s.eq(&string)) +} + +pub(crate) const RAW_IDENTIFIER: &str = "r#"; + +pub(crate) const RUST_KEYWORDS: [&str; 52] = [ + "as", "async", "await", "break", "const", "continue", "crate", "dyn", "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", "union", + "unsafe", "use", "where", "while", "abstract", "become", "box", "do", "final", "macro", + "override", "priv", "try", "typeof", "unsized", "virtual", "yield", +]; diff --git a/src/tests_cfg/mod.rs b/src/tests_cfg/mod.rs index 6bc86aede..d6c80b363 100644 --- a/src/tests_cfg/mod.rs +++ b/src/tests_cfg/mod.rs @@ -7,6 +7,7 @@ pub mod cake_filling_price; pub mod entity_linked; pub mod filling; pub mod fruit; +pub mod rust_keyword; pub mod vendor; pub use cake::Entity as Cake; @@ -15,4 +16,5 @@ pub use cake_filling::Entity as CakeFilling; pub use cake_filling_price::Entity as CakeFillingPrice; pub use filling::Entity as Filling; pub use fruit::Entity as Fruit; +pub use rust_keyword::Entity as RustKeyword; pub use vendor::Entity as Vendor; diff --git a/src/tests_cfg/rust_keyword.rs b/src/tests_cfg/rust_keyword.rs new file mode 100644 index 000000000..90671a347 --- /dev/null +++ b/src/tests_cfg/rust_keyword.rs @@ -0,0 +1,71 @@ +use crate as sea_orm; +use crate::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "rust_keyword")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub testing: i32, + pub rust: i32, + pub keywords: i32, + pub r#as: i32, + pub r#async: i32, + pub r#await: i32, + pub r#break: i32, + pub r#const: i32, + pub r#continue: i32, + pub r#dyn: i32, + pub r#else: i32, + pub r#enum: i32, + pub r#extern: i32, + pub r#false: i32, + pub r#fn: i32, + pub r#for: i32, + pub r#if: i32, + pub r#impl: i32, + pub r#in: i32, + pub r#let: i32, + pub r#loop: i32, + pub r#match: i32, + pub r#mod: i32, + pub r#move: i32, + pub r#mut: i32, + pub r#pub: i32, + pub r#ref: i32, + pub r#return: i32, + pub r#static: i32, + pub r#struct: i32, + pub r#trait: i32, + pub r#true: i32, + pub r#type: i32, + pub r#union: i32, + pub r#unsafe: i32, + pub r#use: i32, + pub r#where: i32, + pub r#while: i32, + pub r#abstract: i32, + pub r#become: i32, + pub r#box: i32, + pub r#do: i32, + pub r#final: i32, + pub r#macro: i32, + pub r#override: i32, + pub r#priv: i32, + pub r#try: i32, + pub r#typeof: i32, + pub r#unsized: i32, + pub r#virtual: i32, + pub r#yield: i32, +} + +#[derive(Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + unreachable!() + } +} + +impl ActiveModelBehavior for ActiveModel {} From f3f24320e9a8ffdbb166d5f5b92c4da513bcfd8f Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 5 Oct 2021 10:23:45 +0800 Subject: [PATCH 2/4] Add test cases --- src/tests_cfg/rust_keyword.rs | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/tests_cfg/rust_keyword.rs b/src/tests_cfg/rust_keyword.rs index 90671a347..299e9c6fe 100644 --- a/src/tests_cfg/rust_keyword.rs +++ b/src/tests_cfg/rust_keyword.rs @@ -9,6 +9,7 @@ pub struct Model { pub testing: i32, pub rust: i32, pub keywords: i32, + pub r#raw_identifier: i32, pub r#as: i32, pub r#async: i32, pub r#await: i32, @@ -69,3 +70,66 @@ impl RelationTrait for Relation { } impl ActiveModelBehavior for ActiveModel {} + +#[cfg(test)] +mod tests { + use crate::tests_cfg::*; + use sea_query::Iden; + + #[test] + fn test_columns() { + assert_eq!(rust_keyword::Column::Id.to_string(), "id".to_owned()); + assert_eq!(rust_keyword::Column::Testing.to_string(), "testing".to_owned()); + assert_eq!(rust_keyword::Column::Rust.to_string(), "rust".to_owned()); + assert_eq!(rust_keyword::Column::Keywords.to_string(), "keywords".to_owned()); + assert_eq!(rust_keyword::Column::RawIdentifier.to_string(), "raw_identifier".to_owned()); + assert_eq!(rust_keyword::Column::As.to_string(), "as".to_owned()); + assert_eq!(rust_keyword::Column::Async.to_string(), "async".to_owned()); + assert_eq!(rust_keyword::Column::Await.to_string(), "await".to_owned()); + assert_eq!(rust_keyword::Column::Break.to_string(), "break".to_owned()); + assert_eq!(rust_keyword::Column::Const.to_string(), "const".to_owned()); + assert_eq!(rust_keyword::Column::Continue.to_string(), "continue".to_owned()); + assert_eq!(rust_keyword::Column::Dyn.to_string(), "dyn".to_owned()); + assert_eq!(rust_keyword::Column::Else.to_string(), "else".to_owned()); + assert_eq!(rust_keyword::Column::Enum.to_string(), "enum".to_owned()); + assert_eq!(rust_keyword::Column::Extern.to_string(), "extern".to_owned()); + assert_eq!(rust_keyword::Column::False.to_string(), "false".to_owned()); + assert_eq!(rust_keyword::Column::Fn.to_string(), "fn".to_owned()); + assert_eq!(rust_keyword::Column::For.to_string(), "for".to_owned()); + assert_eq!(rust_keyword::Column::If.to_string(), "if".to_owned()); + assert_eq!(rust_keyword::Column::Impl.to_string(), "impl".to_owned()); + assert_eq!(rust_keyword::Column::In.to_string(), "in".to_owned()); + assert_eq!(rust_keyword::Column::Let.to_string(), "let".to_owned()); + assert_eq!(rust_keyword::Column::Loop.to_string(), "loop".to_owned()); + assert_eq!(rust_keyword::Column::Match.to_string(), "match".to_owned()); + assert_eq!(rust_keyword::Column::Mod.to_string(), "mod".to_owned()); + assert_eq!(rust_keyword::Column::Move.to_string(), "move".to_owned()); + assert_eq!(rust_keyword::Column::Mut.to_string(), "mut".to_owned()); + assert_eq!(rust_keyword::Column::Pub.to_string(), "pub".to_owned()); + assert_eq!(rust_keyword::Column::Ref.to_string(), "ref".to_owned()); + assert_eq!(rust_keyword::Column::Return.to_string(), "return".to_owned()); + assert_eq!(rust_keyword::Column::Static.to_string(), "static".to_owned()); + assert_eq!(rust_keyword::Column::Struct.to_string(), "struct".to_owned()); + assert_eq!(rust_keyword::Column::Trait.to_string(), "trait".to_owned()); + assert_eq!(rust_keyword::Column::True.to_string(), "true".to_owned()); + assert_eq!(rust_keyword::Column::Type.to_string(), "type".to_owned()); + assert_eq!(rust_keyword::Column::Union.to_string(), "union".to_owned()); + assert_eq!(rust_keyword::Column::Unsafe.to_string(), "unsafe".to_owned()); + assert_eq!(rust_keyword::Column::Use.to_string(), "use".to_owned()); + assert_eq!(rust_keyword::Column::Where.to_string(), "where".to_owned()); + assert_eq!(rust_keyword::Column::While.to_string(), "while".to_owned()); + assert_eq!(rust_keyword::Column::Abstract.to_string(), "abstract".to_owned()); + assert_eq!(rust_keyword::Column::Become.to_string(), "become".to_owned()); + assert_eq!(rust_keyword::Column::Box.to_string(), "box".to_owned()); + assert_eq!(rust_keyword::Column::Do.to_string(), "do".to_owned()); + assert_eq!(rust_keyword::Column::Final.to_string(), "final".to_owned()); + assert_eq!(rust_keyword::Column::Macro.to_string(), "macro".to_owned()); + assert_eq!(rust_keyword::Column::Override.to_string(), "override".to_owned()); + assert_eq!(rust_keyword::Column::Priv.to_string(), "priv".to_owned()); + assert_eq!(rust_keyword::Column::Try.to_string(), "try".to_owned()); + assert_eq!(rust_keyword::Column::Typeof.to_string(), "typeof".to_owned()); + assert_eq!(rust_keyword::Column::Unsized.to_string(), "unsized".to_owned()); + assert_eq!(rust_keyword::Column::Virtual.to_string(), "virtual".to_owned()); + assert_eq!(rust_keyword::Column::Yield.to_string(), "yield".to_owned()); + } +} From 7779ac886eac1609fc1d44a96dea1f00919e2e77 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 5 Oct 2021 10:49:06 +0800 Subject: [PATCH 3/4] Escape rust keyword on codegen --- sea-orm-codegen/src/entity/column.rs | 5 +- sea-orm-codegen/src/entity/writer.rs | 58 ++++++++- sea-orm-codegen/src/lib.rs | 1 + sea-orm-codegen/src/util.rs | 27 +++++ sea-orm-codegen/tests/compact/rust_keyword.rs | 28 +++++ .../tests/expanded/rust_keyword.rs | 73 +++++++++++ src/tests_cfg/rust_keyword.rs | 114 +++++++++--------- 7 files changed, 246 insertions(+), 60 deletions(-) create mode 100644 sea-orm-codegen/src/util.rs create mode 100644 sea-orm-codegen/tests/compact/rust_keyword.rs create mode 100644 sea-orm-codegen/tests/expanded/rust_keyword.rs diff --git a/sea-orm-codegen/src/entity/column.rs b/sea-orm-codegen/src/entity/column.rs index 532f2e915..d3d47cb11 100644 --- a/sea-orm-codegen/src/entity/column.rs +++ b/sea-orm-codegen/src/entity/column.rs @@ -1,3 +1,4 @@ +use crate::util::escape_rust_keyword; use heck::{CamelCase, SnakeCase}; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; @@ -14,11 +15,11 @@ pub struct Column { impl Column { pub fn get_name_snake_case(&self) -> Ident { - format_ident!("{}", self.name.to_snake_case()) + format_ident!("{}", escape_rust_keyword(self.name.to_snake_case())) } pub fn get_name_camel_case(&self) -> Ident { - format_ident!("{}", self.name.to_camel_case()) + format_ident!("{}", escape_rust_keyword(self.name.to_camel_case())) } pub fn get_rs_type(&self) -> TokenStream { diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index 59f545379..5d064f886 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -597,18 +597,71 @@ mod tests { name: "id".to_owned(), }], }, + Entity { + table_name: "rust_keyword".to_owned(), + columns: vec![ + Column { + name: "id".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: true, + not_null: true, + unique: false, + }, + Column { + name: "testing".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + Column { + name: "rust".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + Column { + name: "keywords".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + Column { + name: "type".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + Column { + name: "typeof".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + ], + relations: vec![], + conjunct_relations: vec![], + primary_keys: vec![PrimaryKey { + name: "id".to_owned(), + }], + }, ] } #[test] fn test_gen_expanded_code_blocks() -> io::Result<()> { let entities = setup(); - const ENTITY_FILES: [&str; 5] = [ + const ENTITY_FILES: [&str; 6] = [ include_str!("../../tests/expanded/cake.rs"), include_str!("../../tests/expanded/cake_filling.rs"), include_str!("../../tests/expanded/filling.rs"), include_str!("../../tests/expanded/fruit.rs"), include_str!("../../tests/expanded/vendor.rs"), + include_str!("../../tests/expanded/rust_keyword.rs"), ]; assert_eq!(entities.len(), ENTITY_FILES.len()); @@ -642,12 +695,13 @@ mod tests { #[test] fn test_gen_compact_code_blocks() -> io::Result<()> { let entities = setup(); - const ENTITY_FILES: [&str; 5] = [ + const ENTITY_FILES: [&str; 6] = [ include_str!("../../tests/compact/cake.rs"), include_str!("../../tests/compact/cake_filling.rs"), include_str!("../../tests/compact/filling.rs"), include_str!("../../tests/compact/fruit.rs"), include_str!("../../tests/compact/vendor.rs"), + include_str!("../../tests/compact/rust_keyword.rs"), ]; assert_eq!(entities.len(), ENTITY_FILES.len()); diff --git a/sea-orm-codegen/src/lib.rs b/sea-orm-codegen/src/lib.rs index 07e167bc4..5e637de19 100644 --- a/sea-orm-codegen/src/lib.rs +++ b/sea-orm-codegen/src/lib.rs @@ -1,5 +1,6 @@ mod entity; mod error; +mod util; pub use entity::*; pub use error::*; diff --git a/sea-orm-codegen/src/util.rs b/sea-orm-codegen/src/util.rs new file mode 100644 index 000000000..e752215bf --- /dev/null +++ b/sea-orm-codegen/src/util.rs @@ -0,0 +1,27 @@ +pub(crate) fn escape_rust_keyword(string: T) -> String +where + T: ToString, +{ + let string = string.to_string(); + if is_rust_keyword(&string) { + format!("r#{}", string) + } else { + string + } +} + +pub(crate) fn is_rust_keyword(string: T) -> bool +where + T: ToString, +{ + let string = string.to_string(); + RUST_KEYWORDS.iter().any(|s| s.eq(&string)) +} + +pub(crate) const RUST_KEYWORDS: [&str; 52] = [ + "as", "async", "await", "break", "const", "continue", "crate", "dyn", "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", "union", + "unsafe", "use", "where", "while", "abstract", "become", "box", "do", "final", "macro", + "override", "priv", "try", "typeof", "unsized", "virtual", "yield", +]; diff --git a/sea-orm-codegen/tests/compact/rust_keyword.rs b/sea-orm-codegen/tests/compact/rust_keyword.rs new file mode 100644 index 000000000..9e51bafde --- /dev/null +++ b/sea-orm-codegen/tests/compact/rust_keyword.rs @@ -0,0 +1,28 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "rust_keyword")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub testing: i32, + pub rust: i32, + pub keywords: i32, + pub r#type: i32, + pub r#typeof: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + _ => panic!("No RelationDef"), + } + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded/rust_keyword.rs b/sea-orm-codegen/tests/expanded/rust_keyword.rs new file mode 100644 index 000000000..5c24d71c7 --- /dev/null +++ b/sea-orm-codegen/tests/expanded/rust_keyword.rs @@ -0,0 +1,73 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "rust_keyword" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub id: i32, + pub testing: i32, + pub rust: i32, + pub keywords: i32, + pub r#type: i32, + pub r#typeof: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Testing, + Rust, + Keywords, + Type, + Typeof, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl ColumnTrait for Column { + type EntityName = Entity; + + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Testing => ColumnType::Integer.def(), + Self::Rust => ColumnType::Integer.def(), + Self::Keywords => ColumnType::Integer.def(), + Self::Type => ColumnType::Integer.def(), + Self::Typeof => ColumnType::Integer.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + _ => panic!("No RelationDef"), + } + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/tests_cfg/rust_keyword.rs b/src/tests_cfg/rust_keyword.rs index 299e9c6fe..30052db6e 100644 --- a/src/tests_cfg/rust_keyword.rs +++ b/src/tests_cfg/rust_keyword.rs @@ -60,12 +60,14 @@ pub struct Model { pub r#yield: i32, } -#[derive(Debug, EnumIter)] +#[derive(Copy, Clone, Debug, EnumIter)] pub enum Relation {} impl RelationTrait for Relation { fn def(&self) -> RelationDef { - unreachable!() + match self { + _ => panic!("No RelationDef"), + } } } @@ -73,63 +75,63 @@ impl ActiveModelBehavior for ActiveModel {} #[cfg(test)] mod tests { - use crate::tests_cfg::*; + use crate::tests_cfg::rust_keyword::*; use sea_query::Iden; #[test] fn test_columns() { - assert_eq!(rust_keyword::Column::Id.to_string(), "id".to_owned()); - assert_eq!(rust_keyword::Column::Testing.to_string(), "testing".to_owned()); - assert_eq!(rust_keyword::Column::Rust.to_string(), "rust".to_owned()); - assert_eq!(rust_keyword::Column::Keywords.to_string(), "keywords".to_owned()); - assert_eq!(rust_keyword::Column::RawIdentifier.to_string(), "raw_identifier".to_owned()); - assert_eq!(rust_keyword::Column::As.to_string(), "as".to_owned()); - assert_eq!(rust_keyword::Column::Async.to_string(), "async".to_owned()); - assert_eq!(rust_keyword::Column::Await.to_string(), "await".to_owned()); - assert_eq!(rust_keyword::Column::Break.to_string(), "break".to_owned()); - assert_eq!(rust_keyword::Column::Const.to_string(), "const".to_owned()); - assert_eq!(rust_keyword::Column::Continue.to_string(), "continue".to_owned()); - assert_eq!(rust_keyword::Column::Dyn.to_string(), "dyn".to_owned()); - assert_eq!(rust_keyword::Column::Else.to_string(), "else".to_owned()); - assert_eq!(rust_keyword::Column::Enum.to_string(), "enum".to_owned()); - assert_eq!(rust_keyword::Column::Extern.to_string(), "extern".to_owned()); - assert_eq!(rust_keyword::Column::False.to_string(), "false".to_owned()); - assert_eq!(rust_keyword::Column::Fn.to_string(), "fn".to_owned()); - assert_eq!(rust_keyword::Column::For.to_string(), "for".to_owned()); - assert_eq!(rust_keyword::Column::If.to_string(), "if".to_owned()); - assert_eq!(rust_keyword::Column::Impl.to_string(), "impl".to_owned()); - assert_eq!(rust_keyword::Column::In.to_string(), "in".to_owned()); - assert_eq!(rust_keyword::Column::Let.to_string(), "let".to_owned()); - assert_eq!(rust_keyword::Column::Loop.to_string(), "loop".to_owned()); - assert_eq!(rust_keyword::Column::Match.to_string(), "match".to_owned()); - assert_eq!(rust_keyword::Column::Mod.to_string(), "mod".to_owned()); - assert_eq!(rust_keyword::Column::Move.to_string(), "move".to_owned()); - assert_eq!(rust_keyword::Column::Mut.to_string(), "mut".to_owned()); - assert_eq!(rust_keyword::Column::Pub.to_string(), "pub".to_owned()); - assert_eq!(rust_keyword::Column::Ref.to_string(), "ref".to_owned()); - assert_eq!(rust_keyword::Column::Return.to_string(), "return".to_owned()); - assert_eq!(rust_keyword::Column::Static.to_string(), "static".to_owned()); - assert_eq!(rust_keyword::Column::Struct.to_string(), "struct".to_owned()); - assert_eq!(rust_keyword::Column::Trait.to_string(), "trait".to_owned()); - assert_eq!(rust_keyword::Column::True.to_string(), "true".to_owned()); - assert_eq!(rust_keyword::Column::Type.to_string(), "type".to_owned()); - assert_eq!(rust_keyword::Column::Union.to_string(), "union".to_owned()); - assert_eq!(rust_keyword::Column::Unsafe.to_string(), "unsafe".to_owned()); - assert_eq!(rust_keyword::Column::Use.to_string(), "use".to_owned()); - assert_eq!(rust_keyword::Column::Where.to_string(), "where".to_owned()); - assert_eq!(rust_keyword::Column::While.to_string(), "while".to_owned()); - assert_eq!(rust_keyword::Column::Abstract.to_string(), "abstract".to_owned()); - assert_eq!(rust_keyword::Column::Become.to_string(), "become".to_owned()); - assert_eq!(rust_keyword::Column::Box.to_string(), "box".to_owned()); - assert_eq!(rust_keyword::Column::Do.to_string(), "do".to_owned()); - assert_eq!(rust_keyword::Column::Final.to_string(), "final".to_owned()); - assert_eq!(rust_keyword::Column::Macro.to_string(), "macro".to_owned()); - assert_eq!(rust_keyword::Column::Override.to_string(), "override".to_owned()); - assert_eq!(rust_keyword::Column::Priv.to_string(), "priv".to_owned()); - assert_eq!(rust_keyword::Column::Try.to_string(), "try".to_owned()); - assert_eq!(rust_keyword::Column::Typeof.to_string(), "typeof".to_owned()); - assert_eq!(rust_keyword::Column::Unsized.to_string(), "unsized".to_owned()); - assert_eq!(rust_keyword::Column::Virtual.to_string(), "virtual".to_owned()); - assert_eq!(rust_keyword::Column::Yield.to_string(), "yield".to_owned()); + assert_eq!(Column::Id.to_string().as_str(), "id"); + assert_eq!(Column::Testing.to_string().as_str(), "testing"); + assert_eq!(Column::Rust.to_string().as_str(), "rust"); + assert_eq!(Column::Keywords.to_string().as_str(), "keywords"); + assert_eq!(Column::RawIdentifier.to_string().as_str(), "raw_identifier"); + assert_eq!(Column::As.to_string().as_str(), "as"); + assert_eq!(Column::Async.to_string().as_str(), "async"); + assert_eq!(Column::Await.to_string().as_str(), "await"); + assert_eq!(Column::Break.to_string().as_str(), "break"); + assert_eq!(Column::Const.to_string().as_str(), "const"); + assert_eq!(Column::Continue.to_string().as_str(), "continue"); + assert_eq!(Column::Dyn.to_string().as_str(), "dyn"); + assert_eq!(Column::Else.to_string().as_str(), "else"); + assert_eq!(Column::Enum.to_string().as_str(), "enum"); + assert_eq!(Column::Extern.to_string().as_str(), "extern"); + assert_eq!(Column::False.to_string().as_str(), "false"); + assert_eq!(Column::Fn.to_string().as_str(), "fn"); + assert_eq!(Column::For.to_string().as_str(), "for"); + assert_eq!(Column::If.to_string().as_str(), "if"); + assert_eq!(Column::Impl.to_string().as_str(), "impl"); + assert_eq!(Column::In.to_string().as_str(), "in"); + assert_eq!(Column::Let.to_string().as_str(), "let"); + assert_eq!(Column::Loop.to_string().as_str(), "loop"); + assert_eq!(Column::Match.to_string().as_str(), "match"); + assert_eq!(Column::Mod.to_string().as_str(), "mod"); + assert_eq!(Column::Move.to_string().as_str(), "move"); + assert_eq!(Column::Mut.to_string().as_str(), "mut"); + assert_eq!(Column::Pub.to_string().as_str(), "pub"); + assert_eq!(Column::Ref.to_string().as_str(), "ref"); + assert_eq!(Column::Return.to_string().as_str(), "return"); + assert_eq!(Column::Static.to_string().as_str(), "static"); + assert_eq!(Column::Struct.to_string().as_str(), "struct"); + assert_eq!(Column::Trait.to_string().as_str(), "trait"); + assert_eq!(Column::True.to_string().as_str(), "true"); + assert_eq!(Column::Type.to_string().as_str(), "type"); + assert_eq!(Column::Union.to_string().as_str(), "union"); + assert_eq!(Column::Unsafe.to_string().as_str(), "unsafe"); + assert_eq!(Column::Use.to_string().as_str(), "use"); + assert_eq!(Column::Where.to_string().as_str(), "where"); + assert_eq!(Column::While.to_string().as_str(), "while"); + assert_eq!(Column::Abstract.to_string().as_str(), "abstract"); + assert_eq!(Column::Become.to_string().as_str(), "become"); + assert_eq!(Column::Box.to_string().as_str(), "box"); + assert_eq!(Column::Do.to_string().as_str(), "do"); + assert_eq!(Column::Final.to_string().as_str(), "final"); + assert_eq!(Column::Macro.to_string().as_str(), "macro"); + assert_eq!(Column::Override.to_string().as_str(), "override"); + assert_eq!(Column::Priv.to_string().as_str(), "priv"); + assert_eq!(Column::Try.to_string().as_str(), "try"); + assert_eq!(Column::Typeof.to_string().as_str(), "typeof"); + assert_eq!(Column::Unsized.to_string().as_str(), "unsized"); + assert_eq!(Column::Virtual.to_string().as_str(), "virtual"); + assert_eq!(Column::Yield.to_string().as_str(), "yield"); } } From d6b53abd9500bd02dd00f4121968111820060422 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Wed, 6 Oct 2021 22:24:52 +0800 Subject: [PATCH 4/4] Handle `crate`, `Self` and `self` rust keywords --- sea-orm-codegen/src/entity/writer.rs | 14 ++++++++++ sea-orm-codegen/src/util.rs | 26 ++++++++----------- sea-orm-codegen/tests/compact/rust_keyword.rs | 2 ++ .../tests/expanded/rust_keyword.rs | 6 +++++ sea-orm-macros/src/util.rs | 26 ++++++++----------- src/tests_cfg/rust_keyword.rs | 4 +++ 6 files changed, 48 insertions(+), 30 deletions(-) diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index 5d064f886..17e74130c 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -642,6 +642,20 @@ mod tests { not_null: true, unique: false, }, + Column { + name: "crate".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + Column { + name: "self".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, ], relations: vec![], conjunct_relations: vec![], diff --git a/sea-orm-codegen/src/util.rs b/sea-orm-codegen/src/util.rs index e752215bf..34c46c547 100644 --- a/sea-orm-codegen/src/util.rs +++ b/sea-orm-codegen/src/util.rs @@ -3,25 +3,21 @@ where T: ToString, { let string = string.to_string(); - if is_rust_keyword(&string) { + if RUST_KEYWORDS.iter().any(|s| s.eq(&string)) { format!("r#{}", string) + } else if RUST_SPECIAL_KEYWORDS.iter().any(|s| s.eq(&string)) { + format!("{}_", string) } else { string } } -pub(crate) fn is_rust_keyword(string: T) -> bool -where - T: ToString, -{ - let string = string.to_string(); - RUST_KEYWORDS.iter().any(|s| s.eq(&string)) -} - -pub(crate) const RUST_KEYWORDS: [&str; 52] = [ - "as", "async", "await", "break", "const", "continue", "crate", "dyn", "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", "union", - "unsafe", "use", "where", "while", "abstract", "become", "box", "do", "final", "macro", - "override", "priv", "try", "typeof", "unsized", "virtual", "yield", +pub(crate) const RUST_KEYWORDS: [&str; 49] = [ + "as", "async", "await", "break", "const", "continue", "dyn", "else", "enum", "extern", "false", + "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref", + "return", "static", "struct", "super", "trait", "true", "type", "union", "unsafe", "use", + "where", "while", "abstract", "become", "box", "do", "final", "macro", "override", "priv", + "try", "typeof", "unsized", "virtual", "yield", ]; + +pub(crate) const RUST_SPECIAL_KEYWORDS: [&str; 3] = ["crate", "Self", "self"]; diff --git a/sea-orm-codegen/tests/compact/rust_keyword.rs b/sea-orm-codegen/tests/compact/rust_keyword.rs index 9e51bafde..229eae221 100644 --- a/sea-orm-codegen/tests/compact/rust_keyword.rs +++ b/sea-orm-codegen/tests/compact/rust_keyword.rs @@ -12,6 +12,8 @@ pub struct Model { pub keywords: i32, pub r#type: i32, pub r#typeof: i32, + pub crate_: i32, + pub self_: i32, } #[derive(Copy, Clone, Debug, EnumIter)] diff --git a/sea-orm-codegen/tests/expanded/rust_keyword.rs b/sea-orm-codegen/tests/expanded/rust_keyword.rs index 5c24d71c7..1ab8a6275 100644 --- a/sea-orm-codegen/tests/expanded/rust_keyword.rs +++ b/sea-orm-codegen/tests/expanded/rust_keyword.rs @@ -19,6 +19,8 @@ pub struct Model { pub keywords: i32, pub r#type: i32, pub r#typeof: i32, + pub crate_: i32, + pub self_: i32, } #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] @@ -29,6 +31,8 @@ pub enum Column { Keywords, Type, Typeof, + Crate, + Self_, } #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] @@ -58,6 +62,8 @@ impl ColumnTrait for Column { Self::Keywords => ColumnType::Integer.def(), Self::Type => ColumnType::Integer.def(), Self::Typeof => ColumnType::Integer.def(), + Self::Crate => ColumnType::Integer.def(), + Self::Self_ => ColumnType::Integer.def(), } } } diff --git a/sea-orm-macros/src/util.rs b/sea-orm-macros/src/util.rs index 8929e9e8e..379b486ca 100644 --- a/sea-orm-macros/src/util.rs +++ b/sea-orm-macros/src/util.rs @@ -40,27 +40,23 @@ where T: ToString, { let string = string.to_string(); - if is_rust_keyword(&string) { + if RUST_KEYWORDS.iter().any(|s| s.eq(&string)) { format!("r#{}", string) + } else if RUST_SPECIAL_KEYWORDS.iter().any(|s| s.eq(&string)) { + format!("{}_", string) } else { string } } -pub(crate) fn is_rust_keyword(string: T) -> bool -where - T: ToString, -{ - let string = string.to_string(); - RUST_KEYWORDS.iter().any(|s| s.eq(&string)) -} - pub(crate) const RAW_IDENTIFIER: &str = "r#"; -pub(crate) const RUST_KEYWORDS: [&str; 52] = [ - "as", "async", "await", "break", "const", "continue", "crate", "dyn", "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", "union", - "unsafe", "use", "where", "while", "abstract", "become", "box", "do", "final", "macro", - "override", "priv", "try", "typeof", "unsized", "virtual", "yield", +pub(crate) const RUST_KEYWORDS: [&str; 49] = [ + "as", "async", "await", "break", "const", "continue", "dyn", "else", "enum", "extern", "false", + "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref", + "return", "static", "struct", "super", "trait", "true", "type", "union", "unsafe", "use", + "where", "while", "abstract", "become", "box", "do", "final", "macro", "override", "priv", + "try", "typeof", "unsized", "virtual", "yield", ]; + +pub(crate) const RUST_SPECIAL_KEYWORDS: [&str; 3] = ["crate", "Self", "self"]; diff --git a/src/tests_cfg/rust_keyword.rs b/src/tests_cfg/rust_keyword.rs index 30052db6e..c8662347f 100644 --- a/src/tests_cfg/rust_keyword.rs +++ b/src/tests_cfg/rust_keyword.rs @@ -16,6 +16,7 @@ pub struct Model { pub r#break: i32, pub r#const: i32, pub r#continue: i32, + pub crate_: i32, pub r#dyn: i32, pub r#else: i32, pub r#enum: i32, @@ -35,6 +36,7 @@ pub struct Model { pub r#pub: i32, pub r#ref: i32, pub r#return: i32, + pub self_: i32, pub r#static: i32, pub r#struct: i32, pub r#trait: i32, @@ -92,6 +94,7 @@ mod tests { assert_eq!(Column::Const.to_string().as_str(), "const"); assert_eq!(Column::Continue.to_string().as_str(), "continue"); assert_eq!(Column::Dyn.to_string().as_str(), "dyn"); + assert_eq!(Column::Crate.to_string().as_str(), "crate"); assert_eq!(Column::Else.to_string().as_str(), "else"); assert_eq!(Column::Enum.to_string().as_str(), "enum"); assert_eq!(Column::Extern.to_string().as_str(), "extern"); @@ -110,6 +113,7 @@ mod tests { assert_eq!(Column::Pub.to_string().as_str(), "pub"); assert_eq!(Column::Ref.to_string().as_str(), "ref"); assert_eq!(Column::Return.to_string().as_str(), "return"); + assert_eq!(Column::Self_.to_string().as_str(), "self"); assert_eq!(Column::Static.to_string().as_str(), "static"); assert_eq!(Column::Struct.to_string().as_str(), "struct"); assert_eq!(Column::Trait.to_string().as_str(), "trait");