diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index c875848c..69d70bc3 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -8,6 +8,7 @@ use syntax::ptr::P; use syntax::tokenstream::TokenTree; use bound; +use span; use internals::ast::{Body, Field, Item, Style, Variant}; use internals::{attr, Error}; @@ -44,7 +45,7 @@ pub fn expand_derive_deserialize( let builder = aster::AstBuilder::new().span(span); let impl_item = deserialize_item(cx, &builder, &item); - push(Annotatable::Item(impl_item)) + push(span::record_expansion(cx, impl_item, "Deserialize")) } fn deserialize_item( diff --git a/serde_codegen/src/lib.rs.in b/serde_codegen/src/lib.rs.in index 49726851..08dd5d3c 100644 --- a/serde_codegen/src/lib.rs.in +++ b/serde_codegen/src/lib.rs.in @@ -1,3 +1,4 @@ mod bound; mod de; mod ser; +mod span; diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 0369ee21..3f549c0f 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -6,6 +6,7 @@ use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ptr::P; use bound; +use span; use internals::ast::{Body, Field, Item, Style, Variant}; use internals::{attr, Error}; @@ -38,7 +39,7 @@ pub fn expand_derive_serialize( let builder = aster::AstBuilder::new().span(span); let impl_item = serialize_item(cx, &builder, &item); - push(Annotatable::Item(impl_item)) + push(span::record_expansion(cx, impl_item, "Serialize")) } fn serialize_item( diff --git a/serde_codegen/src/span.rs b/serde_codegen/src/span.rs new file mode 100644 index 00000000..5421868d --- /dev/null +++ b/serde_codegen/src/span.rs @@ -0,0 +1,43 @@ +use syntax::ast; +use syntax::codemap::{self, ExpnId, Span}; +use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax::fold::{self, Folder}; +use syntax::parse::token::intern; +use syntax::ptr::P; + +pub fn record_expansion( + cx: &ExtCtxt, + item: P, + derive: &str, +) -> Annotatable { + let info = codemap::ExpnInfo { + call_site: codemap::DUMMY_SP, + callee: codemap::NameAndSpan { + format: codemap::MacroAttribute(intern(&format!("derive({})", derive))), + span: None, + allow_internal_unstable: false, + }, + }; + let expn_id = cx.codemap().record_expansion(info); + + let mut respanner = Respanner { expn_id: expn_id }; + let item = item.map(|item| respanner.fold_item_simple(item)); + Annotatable::Item(item) +} + +struct Respanner { + expn_id: ExpnId, +} + +impl Folder for Respanner { + fn new_span(&mut self, span: Span) -> Span { + Span { + expn_id: self.expn_id, + .. span + } + } + + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) + } +} diff --git a/serde_macros/Cargo.toml b/serde_macros/Cargo.toml index 3b6b8a95..cd61e284 100644 --- a/serde_macros/Cargo.toml +++ b/serde_macros/Cargo.toml @@ -21,6 +21,7 @@ clippy = { version = "^0.*", optional = true } serde_codegen = { version = "^0.7.12", path = "../serde_codegen", default-features = false, features = ["nightly"] } [dev-dependencies] +clippy = "^0.0.78" compiletest_rs = "^0.2.0" fnv = "1.0" rustc-serialize = "^0.3.16" diff --git a/serde_macros/tests/compile_tests.rs b/serde_macros/tests/compile_tests.rs index 27c212b4..41942522 100644 --- a/serde_macros/tests/compile_tests.rs +++ b/serde_macros/tests/compile_tests.rs @@ -20,6 +20,11 @@ fn run_mode(mode: &'static str) { } #[test] -fn compile_test() { +fn compile_fail() { run_mode("compile-fail"); } + +#[test] +fn run_pass() { + run_mode("run-pass"); +} diff --git a/serde_macros/tests/run-pass/identity-op.rs b/serde_macros/tests/run-pass/identity-op.rs new file mode 100644 index 00000000..dcf8117a --- /dev/null +++ b/serde_macros/tests/run-pass/identity-op.rs @@ -0,0 +1,12 @@ +#![feature(custom_derive, plugin)] +#![plugin(serde_macros, clippy)] + +#![deny(identity_op)] + +// The derived implementation uses 0+1 to add up the number of fields +// serialized, which Clippy warns about. If the expansion info is registered +// correctly, the Clippy lint is not triggered. +#[derive(Serialize)] +struct A { b: u8 } + +fn main() {}