From 4179cab9280c50c6f378071dd287120bbb2145dc Mon Sep 17 00:00:00 2001 From: ilslv <47687266+ilslv@users.noreply.github.com> Date: Fri, 13 Aug 2021 16:55:05 +0300 Subject: [PATCH] Fix raw identifiers expanding as-is in ParseAttrs (#1) Co-authored-by: Kai Ren --- CHANGELOG.md | 14 +++++ Cargo.toml | 6 +-- codegen/Cargo.toml | 4 +- core/Cargo.toml | 2 +- core/src/codegen/parse_attrs.rs | 22 ++++---- tests/parse_attrs.rs | 96 +++++++++++++++++++++++++++++++++ 6 files changed, 129 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7daf31..1e292e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,20 @@ All user visible changes to this project will be documented in this file. This p +## [0.1.1] · 2021-08-13 +[0.1.1]: /../../tree/v0.1.1 + +[Diff](/../../compare/v0.1.0...v0.1.1) + +### Fixed + +- Raw identifiers (with `r#`) expanding as-is. ([#1]) + +[#1]: /../../pull/1 + + + + ## [0.1.0] · 2021-06-25 [0.1.0]: /../../tree/v0.1.0 diff --git a/Cargo.toml b/Cargo.toml index e5c45c0..00073a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "synthez" -version = "0.1.0" +version = "0.1.1" edition = "2018" resolver = "2" description = "Steroids for syn, quote and proc_macro2 crates" @@ -24,8 +24,8 @@ include = ["/src/", "/Cargo.toml", "/CHANGELOG.md", "/LICENSE.md", "/README.md"] full = ["synthez-core/full"] [dependencies] -synthez-codegen = { version = "0.1.0", path = "./codegen" } -synthez-core = { version = "0.1.0", path = "./core" } +synthez-codegen = { version = "0.1.1", path = "./codegen" } +synthez-core = { version = "0.1.1", path = "./core" } [workspace] members = ["codegen", "core"] diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 9339b9c..e6da319 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "synthez-codegen" -version = "0.1.0" +version = "0.1.1" edition = "2018" resolver = "2" description = "Internal codegen shim of synthez crate" @@ -17,7 +17,7 @@ include = ["/src/", "/Cargo.toml", "/README.md"] proc-macro = true [dependencies] -synthez-core = { version = "0.1.0", path = "../core" } +synthez-core = { version = "0.1.1", path = "../core" } [dependencies.proc-macro2] version = "1.0.4" default-features = false diff --git a/core/Cargo.toml b/core/Cargo.toml index 558dc79..7030596 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "synthez-core" -version = "0.1.0" +version = "0.1.1" edition = "2018" resolver = "2" description = "Internal implementations of synthez crate" diff --git a/core/src/codegen/parse_attrs.rs b/core/src/codegen/parse_attrs.rs index f096877..174f2f3 100644 --- a/core/src/codegen/parse_attrs.rs +++ b/core/src/codegen/parse_attrs.rs @@ -3,8 +3,9 @@ use std::{collections::HashSet, convert::TryFrom, iter}; use proc_macro2::{Span, TokenStream}; -use quote::{quote, ToTokens, TokenStreamExt as _}; +use quote::{quote, ToTokens}; use syn::{ + ext::IdentExt as _, parse::{Parse, ParseStream}, token, }; @@ -256,7 +257,8 @@ impl Definition { /// Representation of a [`ParseAttrs`]'s field, used for code generation. #[derive(Debug)] struct Field { - /// [`syn::Ident`] of this [`Field`] in the original code. + /// [`syn::Ident`] of this [`Field`] in the original code (without possible + /// `r#` part). ident: syn::Ident, /// [`syn::Type`] of this [`Field`] (with [`field::Container`]). @@ -292,7 +294,7 @@ impl TryFrom for Field { let ident = field.ident.unwrap(); let mut names = if attrs.args.is_empty() { - iter::once(ident.clone()).collect() + iter::once(ident.unraw()).collect() } else { attrs.args }; @@ -591,16 +593,17 @@ impl Parse for Spanning { } impl ToTokens for Kind { - fn to_tokens(&self, tokens: &mut TokenStream) { + fn to_tokens(&self, out: &mut TokenStream) { let variant = syn::Ident::new_on_call_site(match self { Self::Ident => "Ident", Self::Nested => "Nested", Self::Value(_) => "Value", Self::Map => "Map", }); - tokens.append_all(&[quote! { + (quote! { ::synthez::parse::attrs::kind::#variant - }]); + }) + .to_tokens(out); } } @@ -645,14 +648,15 @@ impl Parse for Spanning { } impl ToTokens for Dedup { - fn to_tokens(&self, tokens: &mut TokenStream) { + fn to_tokens(&self, out: &mut TokenStream) { let variant = syn::Ident::new_on_call_site(match self { Self::Unique => "Unique", Self::First => "First", Self::Last => "Last", }); - tokens.append_all(&[quote! { + (quote! { ::synthez::parse::attrs::dedup::#variant - }]); + }) + .to_tokens(out); } } diff --git a/tests/parse_attrs.rs b/tests/parse_attrs.rs index 0f3eb5b..4d73706 100644 --- a/tests/parse_attrs.rs +++ b/tests/parse_attrs.rs @@ -449,6 +449,35 @@ mod ident { assert_eq!(err, "wrong!"); } } + + mod raw { + use synthez::proc_macro2::Span; + + use super::*; + + #[derive(Debug, Default, ParseAttrs)] + struct Attr { + #[parse(ident)] + r#type: Option, + } + + #[test] + fn is_unrawed() { + let input: syn::DeriveInput = syn::parse_quote! { + #[attr(type)] + struct Dummy; + }; + + let _ident = syn::Ident::new_on_call_site("type"); + let res = Attr::parse_attrs("attr", &input); + assert!(res.is_ok(), "failed: {}", res.unwrap_err()); + + assert_eq!( + res.unwrap().r#type, + Some(syn::Token![type](Span::call_site())), + ); + } + } } mod value { @@ -1043,6 +1072,32 @@ mod value { ); } } + + mod raw { + use super::*; + + #[derive(Debug, Default, ParseAttrs)] + struct Attr { + #[parse(value)] + r#type: Option, + } + + #[test] + fn is_unrawed() { + let input: syn::DeriveInput = syn::parse_quote! { + #[attr(type = minas)] + struct Dummy; + }; + + let res = Attr::parse_attrs("attr", &input); + assert!(res.is_ok(), "failed: {}", res.unwrap_err()); + + assert_eq!( + res.unwrap().r#type, + Some(syn::Ident::new_on_call_site("minas")), + ); + } + } } mod map { @@ -1574,6 +1629,47 @@ mod map { assert_eq!(err, "expected `=`"); } } + + mod raw { + use super::*; + + #[derive(Debug, Default, ParseAttrs)] + struct Attr { + #[parse(map)] + r#type: HashMap, + } + + #[test] + fn is_unrawed() { + let input: syn::DeriveInput = syn::parse_quote! { + #[attr(type minas = "tirith")] + #[attr(type loth = "lorien")] + struct Dummy; + }; + + let res = Attr::parse_attrs("attr", &input); + assert!(res.is_ok(), "failed: {}", res.unwrap_err()); + + let out = res.unwrap().r#type; + assert_eq!(out.len(), 2, "wrong length of {:?}", out); + assert_eq!( + out.get(&syn::Ident::new_on_call_site("minas")) + .map(syn::LitStr::value) + .as_deref(), + Some("tirith"), + "wrong item of {:?}", + out, + ); + assert_eq!( + out.get(&syn::Ident::new_on_call_site("loth")) + .map(syn::LitStr::value) + .as_deref(), + Some("lorien"), + "wrong item of {:?}", + out, + ); + } + } } mod nested {