From 7779ac886eac1609fc1d44a96dea1f00919e2e77 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 5 Oct 2021 10:49:06 +0800 Subject: [PATCH] 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 532f2e91..d3d47cb1 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 59f54537..5d064f88 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 07e167bc..5e637de1 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 00000000..e752215b --- /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 00000000..9e51bafd --- /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 00000000..5c24d71c --- /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 299e9c6f..30052db6 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"); } }