From 6f8b476d34eebd2e0f6dfc59fbef40f500b0ffcf Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 24 Dec 2015 11:21:29 -0500 Subject: [PATCH] fix(derive): Restore #[derive] functionality In the core rust repo, this was migrated into a separate crate. I don't think it's necessary to replicate that crate since all we want is #[derive] support. --- syntex_syntax/src/ext/base.rs | 4 + syntex_syntax/src/ext/deriving/mod.rs | 107 ++++++++++++++++++++++++++ syntex_syntax/src/lib.rs | 1 + 3 files changed, 112 insertions(+) create mode 100644 syntex_syntax/src/ext/deriving/mod.rs diff --git a/syntex_syntax/src/ext/base.rs b/syntex_syntax/src/ext/base.rs index 6f1d828a..e5cb1880 100644 --- a/syntex_syntax/src/ext/base.rs +++ b/syntex_syntax/src/ext/base.rs @@ -466,7 +466,11 @@ fn initial_syntax_expander_table<'feat>(_ecfg: &expand::ExpansionConfig<'feat>) /* syntax_expanders.insert(intern("macro_rules"), MacroRulesTT); + */ + + ext::deriving::register_all(&mut syntax_expanders); + /* if ecfg.enable_quotes() { // Quasi-quoting expanders syntax_expanders.insert(intern("quote_tokens"), diff --git a/syntex_syntax/src/ext/deriving/mod.rs b/syntex_syntax/src/ext/deriving/mod.rs new file mode 100644 index 00000000..b95aedda --- /dev/null +++ b/syntex_syntax/src/ext/deriving/mod.rs @@ -0,0 +1,107 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The compiler code necessary to implement the `#[derive]` extensions. +//! +//! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is +//! the standard library, and "std" is the core library. + +use ast::{MetaItem, MetaWord}; +use attr::AttrMetaMethods; +use ext::base::{ExtCtxt, SyntaxEnv, MultiModifier, Annotatable}; +use ext::build::AstBuilder; +use feature_gate; +use codemap::Span; +use parse::token::{intern, intern_and_get_ident}; + +fn expand_derive(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + annotatable: Annotatable) + -> Annotatable { + annotatable.map_item_or(|item| { + item.map(|mut item| { + if mitem.value_str().is_some() { + cx.span_err(mitem.span, "unexpected value in `derive`"); + } + + let traits = mitem.meta_item_list().unwrap_or(&[]); + if traits.is_empty() { + cx.span_warn(mitem.span, "empty trait list in `derive`"); + } + + for titem in traits.iter().rev() { + let tname = match titem.node { + MetaWord(ref tname) => tname, + _ => { + cx.span_err(titem.span, "malformed `derive` entry"); + continue; + } + }; + + if !(is_builtin_trait(tname) || cx.ecfg.enable_custom_derive()) { + feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic, + "custom_derive", + titem.span, + feature_gate::GateIssue::Language, + feature_gate::EXPLAIN_CUSTOM_DERIVE); + continue; + } + + // #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar] + item.attrs.push(cx.attribute(titem.span, cx.meta_word(titem.span, + intern_and_get_ident(&format!("derive_{}", tname))))); + } + + item + }) + }, |a| { + cx.span_err(span, "`derive` can only be applied to items"); + a + }) +} + +pub fn register_all(env: &mut SyntaxEnv) { + env.insert(intern("derive"), + MultiModifier(Box::new(expand_derive))); +} + +fn is_builtin_trait(name: &str) -> bool { + match name { + "Clone" => true, + + "Hash" => true, + + "RustcEncodable" => true, + + "RustcDecodable" => true, + + "PartialEq" => true, + "Eq" => true, + "PartialOrd" => true, + "Ord" => true, + + "Debug" => true, + + "Default" => true, + + "FromPrimitive" => true, + + "Send" => true, + "Sync" => true, + "Copy" => true, + + // deprecated + "Encodable" => true, + "Decodable" => true, + + _ => false, + } +} diff --git a/syntex_syntax/src/lib.rs b/syntex_syntax/src/lib.rs index 616b5c37..4f5f439e 100644 --- a/syntex_syntax/src/lib.rs +++ b/syntex_syntax/src/lib.rs @@ -97,6 +97,7 @@ pub mod print { pub mod ext { pub mod base; pub mod build; + pub mod deriving; pub mod expand; pub mod mtwt; pub mod quote;