Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Macros 1.1 #530

Merged
merged 8 commits into from
Sep 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 51 additions & 35 deletions serde_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,51 +36,67 @@ include!(concat!(env!("OUT_DIR"), "/lib.rs"));
include!("lib.rs.in");

#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
let src = src.as_ref().to_owned();
let dst = dst.as_ref().to_owned();

let expand_thread = move || {
use syntax::{ast, fold};

/// Strip the serde attributes from the crate.
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
/// Helper folder that strips the serde attributes after the extensions have been expanded.
struct StripAttributeFolder;

impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; }
_ => {}
}

Some(attr)
fn syntex_registry() -> syntex::Registry {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the confusing diff - this is just splitting expand into expand and expand_str with common code in syntex_registry.

use syntax::{ast, fold};

/// Strip the serde attributes from the crate.
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
/// Helper folder that strips the serde attributes after the extensions have been expanded.
struct StripAttributeFolder;

impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; }
_ => {}
}

fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
Some(attr)
}

fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}

let mut reg = syntex::Registry::new();
fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
}

let mut reg = syntex::Registry::new();

reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");

reg.add_decorator("derive_Serialize", ser::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize);

reg.add_post_expansion_pass(strip_attributes);

reg
}

reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");
#[cfg(feature = "with-syntex")]
pub fn expand_str(src: &str) -> Result<String, syntex::Error> {
let src = src.to_owned();

reg.add_decorator("derive_Serialize", ser::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize);
let expand_thread = move || {
syntex_registry().expand_str("", "", &src)
};

reg.add_post_expansion_pass(strip_attributes);
syntex::with_extra_stack(expand_thread)
}

reg.expand("", src, dst)
#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
let src = src.as_ref().to_owned();
let dst = dst.as_ref().to_owned();

let expand_thread = move || {
syntex_registry().expand("", src, dst)
};

syntex::with_extra_stack(expand_thread)
Expand Down
23 changes: 23 additions & 0 deletions serde_derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "serde_derive"
version = "0.8.5"
authors = ["Erick Tryzelaar <[email protected]>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]

[lib]
name = "serde_derive"
rustc-macro = true

[dependencies]
serde_codegen = { version = "=0.8.5", path = "../serde_codegen" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why pin to a particular serde_codegen? Shouldn't it be forward compatible?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reason we pin serde_macros. See #470 (comment). It allows you to use an old nightly with an old serde_derive without pulling in a new serde_codegen that no longer compiles on the old nightly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess what I'm saying is: no it's not forward compatible 😈


[dev-dependencies]
fnv = "1.0"
serde = { version = "0.8.5", path = "../serde" }
serde_test = { version = "0.8.5", path = "../serde_test" }
21 changes: 21 additions & 0 deletions serde_derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#![feature(rustc_macro, rustc_macro_lib)]
#![cfg(not(test))]

extern crate rustc_macro;
extern crate serde_codegen;

use rustc_macro::TokenStream;

#[rustc_macro_derive(Serialize)]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let item = format!("#[derive(Serialize)]\n{}", input);
let expanded = serde_codegen::expand_str(&item).unwrap();
expanded.parse().unwrap()
}

#[rustc_macro_derive(Deserialize)]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let item = format!("#[derive(Deserialize)]\n{}", input);
let expanded = serde_codegen::expand_str(&item).unwrap();
expanded.parse().unwrap()
}
8 changes: 8 additions & 0 deletions serde_derive/tests/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![feature(test, rustc_macro, rustc_attrs)]

#[macro_use]
extern crate serde_derive;

extern crate test;

include!("../../testing/tests/test.rs.in");