expand.rs 56.0 KB
Newer Older
S
Steven Fackler 已提交
1
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 3 4 5 6 7 8 9 10
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11
use ast::{self, Block, Ident, NodeId, PatKind, Path};
J
Jeffrey Seyfried 已提交
12
use ast::{MacStmtStyle, StmtKind, ItemKind};
13
use attr::{self, HasAttrs};
14
use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute, dummy_spanned, respan};
15
use config::{is_test_or_bench, StripUnconfigured};
16
use errors::FatalError;
P
Patrick Walton 已提交
17
use ext::base::*;
18
use ext::derive::{add_derived_markers, collect_derives};
19
use ext::hygiene::{Mark, SyntaxContext};
20
use ext::placeholders::{placeholder, PlaceholderExpander};
21
use feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
J
John Clements 已提交
22
use fold;
23
use fold::*;
J
Jeffrey Seyfried 已提交
24 25
use parse::{DirectoryOwnership, PResult};
use parse::token::{self, Token};
N
Nick Cameron 已提交
26
use parse::parser::Parser;
27
use ptr::P;
28
use symbol::Symbol;
29
use symbol::keywords;
30
use syntax_pos::{Span, DUMMY_SP, FileName};
31
use syntax_pos::hygiene::ExpnFormat;
J
Jeffrey Seyfried 已提交
32
use tokenstream::{TokenStream, TokenTree};
33
use util::small_vector::SmallVector;
34
use visit::Visitor;
35

36
use std::collections::HashMap;
37 38
use std::fs::File;
use std::io::Read;
39
use std::mem;
J
Jeffrey Seyfried 已提交
40
use std::rc::Rc;
41
use std::path::PathBuf;
42

43
macro_rules! expansions {
44
    ($($kind:ident: $ty:ty [$($vec:ident, $ty_elt:ty)*], $kind_name:expr, .$make:ident,
45 46
            $(.$fold:ident)*  $(lift .$fold_elt:ident)*,
            $(.$visit:ident)*  $(lift .$visit_elt:ident)*;)*) => {
47
        #[derive(Copy, Clone, PartialEq, Eq)]
48 49
        pub enum ExpansionKind { OptExpr, $( $kind, )*  }
        pub enum Expansion { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* }
50 51

        impl ExpansionKind {
52
            pub fn name(self) -> &'static str {
53 54 55 56 57
                match self {
                    ExpansionKind::OptExpr => "expression",
                    $( ExpansionKind::$kind => $kind_name, )*
                }
            }
J
Jeffrey Seyfried 已提交
58

59 60 61 62 63 64 65
            fn make_from<'a>(self, result: Box<MacResult + 'a>) -> Option<Expansion> {
                match self {
                    ExpansionKind::OptExpr => result.make_expr().map(Some).map(Expansion::OptExpr),
                    $( ExpansionKind::$kind => result.$make().map(Expansion::$kind), )*
                }
            }
        }
66

67
        impl Expansion {
68
            pub fn make_opt_expr(self) -> Option<P<ast::Expr>> {
69 70 71 72 73
                match self {
                    Expansion::OptExpr(expr) => expr,
                    _ => panic!("Expansion::make_* called on the wrong kind of expansion"),
                }
            }
74
            $( pub fn $make(self) -> $ty {
75 76 77 78 79
                match self {
                    Expansion::$kind(ast) => ast,
                    _ => panic!("Expansion::make_* called on the wrong kind of expansion"),
                }
            } )*
80

81
            pub fn fold_with<F: Folder>(self, folder: &mut F) -> Self {
82 83 84 85 86 87 88 89
                use self::Expansion::*;
                match self {
                    OptExpr(expr) => OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))),
                    $($( $kind(ast) => $kind(folder.$fold(ast)), )*)*
                    $($( $kind(ast) => {
                        $kind(ast.into_iter().flat_map(|ast| folder.$fold_elt(ast)).collect())
                    }, )*)*
                }
90
            }
91

92
            pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
93 94 95 96
                match *self {
                    Expansion::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
                    Expansion::OptExpr(None) => {}
                    $($( Expansion::$kind(ref ast) => visitor.$visit(ast), )*)*
97
                    $($( Expansion::$kind(ref ast) => for ast in &ast[..] {
98 99 100 101
                        visitor.$visit_elt(ast);
                    }, )*)*
                }
            }
102
        }
103 104 105 106 107 108 109 110 111 112 113 114

        impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
            fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
                self.expand(Expansion::OptExpr(Some(expr))).make_opt_expr()
            }
            $($(fn $fold(&mut self, node: $ty) -> $ty {
                self.expand(Expansion::$kind(node)).$make()
            })*)*
            $($(fn $fold_elt(&mut self, node: $ty_elt) -> $ty {
                self.expand(Expansion::$kind(SmallVector::one(node))).$make()
            })*)*
        }
115 116 117 118 119 120

        impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
            $(fn $make(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>) -> Option<$ty> {
                Some(self.make(ExpansionKind::$kind).$make())
            })*
        }
121
    }
122 123
}

124
expansions! {
125 126 127
    Expr: P<ast::Expr> [], "expression", .make_expr, .fold_expr, .visit_expr;
    Pat: P<ast::Pat>   [], "pattern",    .make_pat,  .fold_pat,  .visit_pat;
    Ty: P<ast::Ty>     [], "type",       .make_ty,   .fold_ty,   .visit_ty;
128
    Stmts: SmallVector<ast::Stmt> [SmallVector, ast::Stmt],
129
        "statement",  .make_stmts,       lift .fold_stmt, lift .visit_stmt;
130
    Items: SmallVector<P<ast::Item>> [SmallVector, P<ast::Item>],
131
        "item",       .make_items,       lift .fold_item, lift .visit_item;
132
    TraitItems: SmallVector<ast::TraitItem> [SmallVector, ast::TraitItem],
133
        "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item;
134
    ImplItems: SmallVector<ast::ImplItem> [SmallVector, ast::ImplItem],
135
        "impl item",  .make_impl_items,  lift .fold_impl_item,  lift .visit_impl_item;
136 137
    ForeignItems: SmallVector<ast::ForeignItem> [SmallVector, ast::ForeignItem],
        "foreign item", .make_foreign_items, lift .fold_foreign_item, lift .visit_foreign_item;
138 139
}

140
impl ExpansionKind {
141 142
    fn dummy(self, span: Span) -> Option<Expansion> {
        self.make_from(DummyResult::any(span))
143
    }
144 145 146 147 148 149 150 151 152 153

    fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I) -> Expansion {
        let items = items.into_iter();
        match self {
            ExpansionKind::Items =>
                Expansion::Items(items.map(Annotatable::expect_item).collect()),
            ExpansionKind::ImplItems =>
                Expansion::ImplItems(items.map(Annotatable::expect_impl_item).collect()),
            ExpansionKind::TraitItems =>
                Expansion::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
154 155
            ExpansionKind::ForeignItems =>
                Expansion::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()),
156 157 158
            _ => unreachable!(),
        }
    }
159
}
160

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
fn macro_bang_format(path: &ast::Path) -> ExpnFormat {
    // We don't want to format a path using pretty-printing,
    // `format!("{}", path)`, because that tries to insert
    // line-breaks and is slow.
    let mut path_str = String::with_capacity(64);
    for (i, segment) in path.segments.iter().enumerate() {
        if i != 0 {
            path_str.push_str("::");
        }

        if segment.identifier.name != keywords::CrateRoot.name() &&
            segment.identifier.name != keywords::DollarCrate.name()
        {
            path_str.push_str(&segment.identifier.name.as_str())
        }
    }

    MacroBang(Symbol::intern(&path_str))
}

181
pub struct Invocation {
182
    pub kind: InvocationKind,
183
    expansion_kind: ExpansionKind,
184
    pub expansion_data: ExpansionData,
185 186
}

187
pub enum InvocationKind {
188 189 190 191 192 193
    Bang {
        mac: ast::Mac,
        ident: Option<Ident>,
        span: Span,
    },
    Attr {
194
        attr: Option<ast::Attribute>,
J
Jeffrey Seyfried 已提交
195
        traits: Vec<Path>,
196 197
        item: Annotatable,
    },
198
    Derive {
J
Jeffrey Seyfried 已提交
199
        path: Path,
200 201
        item: Annotatable,
    },
202
}
203

204 205 206 207
impl Invocation {
    fn span(&self) -> Span {
        match self.kind {
            InvocationKind::Bang { span, .. } => span,
208
            InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span,
J
Jeffrey Seyfried 已提交
209 210
            InvocationKind::Attr { attr: None, .. } => DUMMY_SP,
            InvocationKind::Derive { ref path, .. } => path.span,
211 212 213 214
        }
    }
}

215
pub struct MacroExpander<'a, 'b:'a> {
216
    pub cx: &'a mut ExtCtxt<'b>,
217
    monotonic: bool, // c.f. `cx.monotonic_expander()`
N
Nick Cameron 已提交
218 219 220
}

impl<'a, 'b> MacroExpander<'a, 'b> {
221
    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
222
        MacroExpander { cx: cx, monotonic: monotonic }
N
Nick Cameron 已提交
223
    }
224

225 226
    pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
        let mut module = ModuleData {
227
            mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
228 229 230 231
            directory: match self.cx.codemap().span_to_unmapped_path(krate.span) {
                FileName::Real(path) => path,
                other => PathBuf::from(other.to_string()),
            },
232 233
        };
        module.directory.pop();
234
        self.cx.root_path = module.directory.clone();
235
        self.cx.current_expansion.module = Rc::new(module);
236
        self.cx.current_expansion.crate_span = Some(krate.span);
237

238 239
        let orig_mod_span = krate.module.inner;

240 241 242 243 244 245
        let krate_item = Expansion::Items(SmallVector::one(P(ast::Item {
            attrs: krate.attrs,
            span: krate.span,
            node: ast::ItemKind::Mod(krate.module),
            ident: keywords::Invalid.ident(),
            id: ast::DUMMY_NODE_ID,
246
            vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
247
            tokens: None,
248 249
        })));

250
        match self.expand(krate_item).make_items().pop().map(P::into_inner) {
251
            Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
252 253 254
                krate.attrs = attrs;
                krate.module = module;
            },
255 256 257 258 259 260 261 262
            None => {
                // Resolution failed so we return an empty expansion
                krate.attrs = vec![];
                krate.module = ast::Mod {
                    inner: orig_mod_span,
                    items: vec![],
                };
            },
263 264
            _ => unreachable!(),
        };
265
        self.cx.trace_macros_diag();
266 267 268 269 270
        krate
    }

    // Fully expand all the invocations in `expansion`.
    fn expand(&mut self, expansion: Expansion) -> Expansion {
271 272 273
        let orig_expansion_data = self.cx.current_expansion.clone();
        self.cx.current_expansion.depth = 0;

274
        let (expansion, mut invocations) = self.collect_invocations(expansion, &[]);
275
        self.resolve_imports();
276 277
        invocations.reverse();

J
Jeffrey Seyfried 已提交
278
        let mut expansions = Vec::new();
279
        let mut derives = HashMap::new();
280 281 282
        let mut undetermined_invocations = Vec::new();
        let (mut progress, mut force) = (false, !self.monotonic);
        loop {
283
            let mut invoc = if let Some(invoc) = invocations.pop() {
284 285
                invoc
            } else {
286 287
                self.resolve_imports();
                if undetermined_invocations.is_empty() { break }
288 289 290 291 292 293 294
                invocations = mem::replace(&mut undetermined_invocations, Vec::new());
                force = !mem::replace(&mut progress, false);
                continue
            };

            let scope =
                if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
295
            let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) {
296 297 298 299 300 301 302 303 304
                Ok(ext) => Some(ext),
                Err(Determinacy::Determined) => None,
                Err(Determinacy::Undetermined) => {
                    undetermined_invocations.push(invoc);
                    continue
                }
            };

            progress = true;
305 306
            let ExpansionData { depth, mark, .. } = invoc.expansion_data;
            self.cx.current_expansion = invoc.expansion_data.clone();
307

308
            self.cx.current_expansion.mark = scope;
309 310 311
            // FIXME(jseyfried): Refactor out the following logic
            let (expansion, new_invocations) = if let Some(ext) = ext {
                if let Some(ext) = ext {
312
                    let dummy = invoc.expansion_kind.dummy(invoc.span()).unwrap();
313
                    let expansion = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
314 315
                    self.collect_invocations(expansion, &[])
                } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
316 317
                    if !item.derive_allowed() {
                        let attr = attr::find_by_name(item.attrs(), "derive")
318 319 320 321 322 323 324 325 326 327 328 329
                            .expect("`derive` attribute should exist");
                        let span = attr.span;
                        let mut err = self.cx.mut_span_err(span,
                                                           "`derive` may only be applied to \
                                                            structs, enums and unions");
                        if let ast::AttrStyle::Inner = attr.style {
                            let trait_list = traits.iter()
                                .map(|t| format!("{}", t)).collect::<Vec<_>>();
                            let suggestion = format!("#[derive({})]", trait_list.join(", "));
                            err.span_suggestion(span, "try an outer attribute", suggestion);
                        }
                        err.emit();
330 331
                    }

332
                    let item = self.fully_configure(item)
333
                        .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
334
                    let item_with_markers =
335
                        add_derived_markers(&mut self.cx, item.span(), &traits, item.clone());
336 337
                    let derives = derives.entry(invoc.expansion_data.mark).or_insert_with(Vec::new);

J
Jeffrey Seyfried 已提交
338
                    for path in &traits {
J
Jeffrey Seyfried 已提交
339
                        let mark = Mark::fresh(self.cx.current_expansion.mark);
340
                        derives.push(mark);
341
                        let item = match self.cx.resolver.resolve_macro(
J
Jeffrey Seyfried 已提交
342
                                Mark::root(), path, MacroKind::Derive, false) {
343
                            Ok(ext) => match *ext {
344
                                BuiltinDerive(..) => item_with_markers.clone(),
345 346 347 348 349
                                _ => item.clone(),
                            },
                            _ => item.clone(),
                        };
                        invocations.push(Invocation {
J
Jeffrey Seyfried 已提交
350
                            kind: InvocationKind::Derive { path: path.clone(), item: item },
351 352
                            expansion_kind: invoc.expansion_kind,
                            expansion_data: ExpansionData {
353
                                mark,
354 355 356 357 358 359 360 361 362 363 364
                                ..invoc.expansion_data.clone()
                            },
                        });
                    }
                    let expansion = invoc.expansion_kind
                        .expect_from_annotatables(::std::iter::once(item_with_markers));
                    self.collect_invocations(expansion, derives)
                } else {
                    unreachable!()
                }
            } else {
365
                self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()).unwrap(), &[])
366
            };
367

J
Jeffrey Seyfried 已提交
368
            if expansions.len() < depth {
369 370
                expansions.push(Vec::new());
            }
371
            expansions[depth - 1].push((mark, expansion));
372
            if !self.cx.ecfg.single_step {
373 374 375 376
                invocations.extend(new_invocations.into_iter().rev());
            }
        }

377 378
        self.cx.current_expansion = orig_expansion_data;

379
        let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
380 381
        while let Some(expansions) = expansions.pop() {
            for (mark, expansion) in expansions.into_iter().rev() {
382
                let derives = derives.remove(&mark).unwrap_or_else(Vec::new);
383
                placeholder_expander.add(NodeId::placeholder_from_mark(mark), expansion, derives);
384 385 386
            }
        }

J
Jeffrey Seyfried 已提交
387
        expansion.fold_with(&mut placeholder_expander)
388 389
    }

390 391 392 393 394 395 396 397
    fn resolve_imports(&mut self) {
        if self.monotonic {
            let err_count = self.cx.parse_sess.span_diagnostic.err_count();
            self.cx.resolver.resolve_imports();
            self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
        }
    }

398 399
    fn collect_invocations(&mut self, expansion: Expansion, derives: &[Mark])
                           -> (Expansion, Vec<Invocation>) {
400 401 402 403 404 405 406 407 408
        let result = {
            let mut collector = InvocationCollector {
                cfg: StripUnconfigured {
                    should_test: self.cx.ecfg.should_test,
                    sess: self.cx.parse_sess,
                    features: self.cx.ecfg.features,
                },
                cx: self.cx,
                invocations: Vec::new(),
409
                monotonic: self.monotonic,
410 411 412
            };
            (expansion.fold_with(&mut collector), collector.invocations)
        };
413

414
        if self.monotonic {
415
            let err_count = self.cx.parse_sess.span_diagnostic.err_count();
416
            let mark = self.cx.current_expansion.mark;
417
            self.cx.resolver.visit_expansion(mark, &result.0, derives);
418
            self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
419 420
        }

421
        result
422
    }
423

424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
    fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
        let mut cfg = StripUnconfigured {
            should_test: self.cx.ecfg.should_test,
            sess: self.cx.parse_sess,
            features: self.cx.ecfg.features,
        };
        // Since the item itself has already been configured by the InvocationCollector,
        // we know that fold result vector will contain exactly one element
        match item {
            Annotatable::Item(item) => {
                Annotatable::Item(cfg.fold_item(item).pop().unwrap())
            }
            Annotatable::TraitItem(item) => {
                Annotatable::TraitItem(item.map(|item| cfg.fold_trait_item(item).pop().unwrap()))
            }
            Annotatable::ImplItem(item) => {
                Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap()))
            }
442 443 444 445 446
            Annotatable::ForeignItem(item) => {
                Annotatable::ForeignItem(
                    item.map(|item| cfg.fold_foreign_item(item).pop().unwrap())
                )
            }
447 448 449 450 451 452
            Annotatable::Stmt(stmt) => {
                Annotatable::Stmt(stmt.map(|stmt| cfg.fold_stmt(stmt).pop().unwrap()))
            }
            Annotatable::Expr(expr) => {
                Annotatable::Expr(cfg.fold_expr(expr))
            }
453 454 455
        }
    }

456
    fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<Expansion> {
457
        let result = match invoc.kind {
458 459 460
            InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?,
            InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?,
            InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext)?,
461 462 463 464 465
        };

        if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
            let info = self.cx.current_expansion.mark.expn_info().unwrap();
            let suggested_limit = self.cx.ecfg.recursion_limit * 2;
466
            let mut err = self.cx.struct_span_err(info.call_site,
467 468 469 470 471 472
                &format!("recursion limit reached while expanding the macro `{}`",
                         info.callee.name()));
            err.help(&format!(
                "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                suggested_limit));
            err.emit();
473
            self.cx.trace_macros_diag();
474
            FatalError.raise();
475
        }
476

477
        Some(result)
478 479
    }

480 481
    fn expand_attr_invoc(&mut self,
                         invoc: Invocation,
482
                         ext: &SyntaxExtension)
483
                         -> Option<Expansion> {
484 485
        let Invocation { expansion_kind: kind, .. } = invoc;
        let (attr, item) = match invoc.kind {
486
            InvocationKind::Attr { attr, item, .. } => (attr?, item),
487 488 489 490
            _ => unreachable!(),
        };

        attr::mark_used(&attr);
491
        invoc.expansion_data.mark.set_expn_info(ExpnInfo {
492 493
            call_site: attr.span,
            callee: NameAndSpan {
J
Jeffrey Seyfried 已提交
494
                format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
495
                span: None,
496
                allow_internal_unstable: false,
497
                allow_internal_unsafe: false,
498 499 500
            }
        });

501
        match *ext {
502
            MultiModifier(ref mac) => {
503 504
                let meta = attr.parse_meta(self.cx.parse_sess)
                               .map_err(|mut e| { e.emit(); }).ok()?;
505
                let item = mac.expand(self.cx, attr.span, &meta, item);
506
                Some(kind.expect_from_annotatables(item))
507 508 509
            }
            MultiDecorator(ref mac) => {
                let mut items = Vec::new();
510 511
                let meta = attr.parse_meta(self.cx.parse_sess)
                               .expect("derive meta should already have been parsed");
512
                mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item));
513
                items.push(item);
514
                Some(kind.expect_from_annotatables(items))
515
            }
516
            AttrProcMacro(ref mac) => {
J
Jeffrey Seyfried 已提交
517 518
                let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item {
                    Annotatable::Item(item) => token::NtItem(item),
519 520
                    Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
                    Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
521
                    Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
522 523
                    Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
                    Annotatable::Expr(expr) => token::NtExpr(expr),
J
Jeffrey Seyfried 已提交
524 525 526
                })).into();
                let tok_result = mac.expand(self.cx, attr.span, attr.tokens, item_tok);
                self.parse_expansion(tok_result, kind, &attr.path, attr.span)
527
            }
528
            ProcMacroDerive(..) | BuiltinDerive(..) => {
J
Jeffrey Seyfried 已提交
529
                self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path));
530
                self.cx.trace_macros_diag();
531 532 533
                kind.dummy(attr.span)
            }
            _ => {
J
Jeffrey Seyfried 已提交
534
                let msg = &format!("macro `{}` may not be used in attributes", attr.path);
535
                self.cx.span_err(attr.span, msg);
536
                self.cx.trace_macros_diag();
537 538
                kind.dummy(attr.span)
            }
539
        }
540 541 542
    }

    /// Expand a macro invocation. Returns the result of expansion.
543 544
    fn expand_bang_invoc(&mut self,
                         invoc: Invocation,
545
                         ext: &SyntaxExtension)
546
                         -> Option<Expansion> {
547
        let (mark, kind) = (invoc.expansion_data.mark, invoc.expansion_kind);
548 549
        let (mac, ident, span) = match invoc.kind {
            InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
550 551
            _ => unreachable!(),
        };
J
Jeffrey Seyfried 已提交
552
        let path = &mac.node.path;
553

554
        let ident = ident.unwrap_or_else(|| keywords::Invalid.ident());
555 556
        let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture
                                          def_site_span: Option<Span>,
557
                                          allow_internal_unstable,
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
                                          allow_internal_unsafe,
                                          // can't infer this type
                                          unstable_feature: Option<(Symbol, u32)>| {

            // feature-gate the macro invocation
            if let Some((feature, issue)) = unstable_feature {
                let crate_span = this.cx.current_expansion.crate_span.unwrap();
                // don't stability-check macros in the same crate
                // (the only time this is null is for syntax extensions registered as macros)
                if def_site_span.map_or(false, |def_span| !crate_span.contains(def_span))
                    && !span.allows_unstable() && this.cx.ecfg.features.map_or(true, |feats| {
                    // macro features will count as lib features
                    !feats.declared_lib_features.iter().any(|&(feat, _)| feat == feature)
                }) {
                    let explain = format!("macro {}! is unstable", path);
                    emit_feature_err(this.cx.parse_sess, &*feature.as_str(), span,
                                     GateIssue::Library(Some(issue)), &explain);
                    this.cx.trace_macros_diag();
                    return Err(kind.dummy(span));
                }
            }

J
Jeffrey Seyfried 已提交
580
            if ident.name != keywords::Invalid.name() {
581 582 583 584
                let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident);
                this.cx.span_err(path.span, &msg);
                this.cx.trace_macros_diag();
                return Err(kind.dummy(span));
J
Jeffrey Seyfried 已提交
585 586 587 588
            }
            mark.set_expn_info(ExpnInfo {
                call_site: span,
                callee: NameAndSpan {
589
                    format: macro_bang_format(path),
J
Jeffrey Seyfried 已提交
590
                    span: def_site_span,
591 592
                    allow_internal_unstable,
                    allow_internal_unsafe,
J
Jeffrey Seyfried 已提交
593 594 595 596 597
                },
            });
            Ok(())
        };

598
        let opt_expanded = match *ext {
599
            DeclMacro(ref expand, def_span) => {
600 601 602
                if let Err(dummy_span) = validate_and_set_expn_info(self, def_span.map(|(_, s)| s),
                                                                    false, false, None) {
                    dummy_span
603 604
                } else {
                    kind.make_from(expand.expand(self.cx, span, mac.node.stream()))
605
                }
J
Jeffrey Seyfried 已提交
606
            }
607

608 609 610 611
            NormalTT {
                ref expander,
                def_info,
                allow_internal_unstable,
612 613
                allow_internal_unsafe,
                unstable_feature,
614
            } => {
615 616 617 618 619
                if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
                                                                    allow_internal_unstable,
                                                                    allow_internal_unsafe,
                                                                    unstable_feature) {
                    dummy_span
620 621
                } else {
                    kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
J
Jeffrey Seyfried 已提交
622
                }
623 624 625 626 627
            }

            IdentTT(ref expander, tt_span, allow_internal_unstable) => {
                if ident.name == keywords::Invalid.name() {
                    self.cx.span_err(path.span,
J
Jeffrey Seyfried 已提交
628
                                    &format!("macro {}! expects an ident argument", path));
629
                    self.cx.trace_macros_diag();
630 631 632 633 634 635 636 637 638 639 640
                    kind.dummy(span)
                } else {
                    invoc.expansion_data.mark.set_expn_info(ExpnInfo {
                        call_site: span,
                        callee: NameAndSpan {
                            format: macro_bang_format(path),
                            span: tt_span,
                            allow_internal_unstable,
                            allow_internal_unsafe: false,
                        }
                    });
641

642 643 644
                    let input: Vec<_> = mac.node.stream().into_trees().collect();
                    kind.make_from(expander.expand(self.cx, span, ident, input))
                }
645 646
            }

647
            MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => {
648
                self.cx.span_err(path.span,
J
Jeffrey Seyfried 已提交
649
                                 &format!("`{}` can only be used in attributes", path));
650
                self.cx.trace_macros_diag();
651
                kind.dummy(span)
652
            }
653

654
            ProcMacroDerive(..) | BuiltinDerive(..) => {
J
Jeffrey Seyfried 已提交
655
                self.cx.span_err(path.span, &format!("`{}` is a derive mode", path));
656
                self.cx.trace_macros_diag();
657
                kind.dummy(span)
658 659
            }

660
            ProcMacro(ref expandfun) => {
661 662
                if ident.name != keywords::Invalid.name() {
                    let msg =
J
Jeffrey Seyfried 已提交
663
                        format!("macro {}! expects no ident argument, given '{}'", path, ident);
N
Nick Cameron 已提交
664
                    self.cx.span_err(path.span, &msg);
665
                    self.cx.trace_macros_diag();
666 667 668 669 670 671 672 673 674 675 676 677 678 679
                    kind.dummy(span)
                } else {
                    invoc.expansion_data.mark.set_expn_info(ExpnInfo {
                        call_site: span,
                        callee: NameAndSpan {
                            format: macro_bang_format(path),
                            // FIXME procedural macros do not have proper span info
                            // yet, when they do, we should use it here.
                            span: None,
                            // FIXME probably want to follow macro_rules macros here.
                            allow_internal_unstable: false,
                            allow_internal_unsafe: false,
                        },
                    });
680

681 682 683
                    let tok_result = expandfun.expand(self.cx, span, mac.node.stream());
                    self.parse_expansion(tok_result, kind, path, span)
                }
684
            }
685 686
        };

687 688 689
        if opt_expanded.is_some() {
            opt_expanded
        } else {
690 691 692
            let msg = format!("non-{kind} macro in {kind} position: {name}",
                              name = path.segments[0].identifier.name, kind = kind.name());
            self.cx.span_err(path.span, &msg);
693
            self.cx.trace_macros_diag();
694
            kind.dummy(span)
695
        }
696
    }
J
Jeffrey Seyfried 已提交
697

698
    /// Expand a derive invocation. Returns the result of expansion.
699 700
    fn expand_derive_invoc(&mut self,
                           invoc: Invocation,
701
                           ext: &SyntaxExtension)
702
                           -> Option<Expansion> {
703
        let Invocation { expansion_kind: kind, .. } = invoc;
J
Jeffrey Seyfried 已提交
704 705
        let (path, item) = match invoc.kind {
            InvocationKind::Derive { path, item } => (path, item),
706 707
            _ => unreachable!(),
        };
708 709 710
        if !item.derive_allowed() {
            return None;
        }
711

J
Jeffrey Seyfried 已提交
712 713 714
        let pretty_name = Symbol::intern(&format!("derive({})", path));
        let span = path.span;
        let attr = ast::Attribute {
715 716
            path, span,
            tokens: TokenStream::empty(),
J
Jeffrey Seyfried 已提交
717 718 719
            // irrelevant:
            id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false,
        };
720

721
        let mut expn_info = ExpnInfo {
722
            call_site: span,
723
            callee: NameAndSpan {
724
                format: MacroAttribute(pretty_name),
J
Jeffrey Seyfried 已提交
725
                span: None,
726
                allow_internal_unstable: false,
727
                allow_internal_unsafe: false,
728
            }
729
        };
730 731

        match *ext {
732
            ProcMacroDerive(ref ext, _) => {
733
                invoc.expansion_data.mark.set_expn_info(expn_info);
734
                let span = span.with_ctxt(self.cx.backtrace());
J
Jeffrey Seyfried 已提交
735 736 737 738 739
                let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
                    name: keywords::Invalid.name(),
                    span: DUMMY_SP,
                    node: ast::MetaItemKind::Word,
                };
740
                Some(kind.expect_from_annotatables(ext.expand(self.cx, span, &dummy, item)))
741
            }
742
            BuiltinDerive(func) => {
743 744
                expn_info.callee.allow_internal_unstable = true;
                invoc.expansion_data.mark.set_expn_info(expn_info);
745
                let span = span.with_ctxt(self.cx.backtrace());
746
                let mut items = Vec::new();
747 748
                func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a));
                Some(kind.expect_from_annotatables(items))
749 750
            }
            _ => {
J
Jeffrey Seyfried 已提交
751
                let msg = &format!("macro `{}` may not be used for derive attributes", attr.path);
752
                self.cx.span_err(span, msg);
753
                self.cx.trace_macros_diag();
754
                kind.dummy(span)
755 756 757 758
            }
        }
    }

759 760 761 762 763 764
    fn parse_expansion(&mut self,
                       toks: TokenStream,
                       kind: ExpansionKind,
                       path: &Path,
                       span: Span)
                       -> Option<Expansion> {
765
        let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
766 767 768 769 770
        match parser.parse_expansion(kind, false) {
            Ok(expansion) => {
                parser.ensure_complete_parse(path, kind.name(), span);
                Some(expansion)
            }
J
Jeffrey Seyfried 已提交
771
            Err(mut err) => {
772
                err.set_span(span);
J
Jeffrey Seyfried 已提交
773
                err.emit();
774
                self.cx.trace_macros_diag();
775
                kind.dummy(span)
J
Jeffrey Seyfried 已提交
776
            }
777
        }
J
Jeffrey Seyfried 已提交
778
    }
779 780
}

781
impl<'a> Parser<'a> {
J
Jeffrey Seyfried 已提交
782 783
    pub fn parse_expansion(&mut self, kind: ExpansionKind, macro_legacy_warnings: bool)
                           -> PResult<'a, Expansion> {
784 785
        Ok(match kind {
            ExpansionKind::Items => {
786
                let mut items = SmallVector::new();
787 788 789 790 791 792
                while let Some(item) = self.parse_item()? {
                    items.push(item);
                }
                Expansion::Items(items)
            }
            ExpansionKind::TraitItems => {
793
                let mut items = SmallVector::new();
794
                while self.token != token::Eof {
795
                    items.push(self.parse_trait_item(&mut false)?);
796 797 798 799
                }
                Expansion::TraitItems(items)
            }
            ExpansionKind::ImplItems => {
800
                let mut items = SmallVector::new();
801
                while self.token != token::Eof {
802
                    items.push(self.parse_impl_item(&mut false)?);
803 804 805
                }
                Expansion::ImplItems(items)
            }
806 807 808 809 810 811 812 813 814
            ExpansionKind::ForeignItems => {
                let mut items = SmallVector::new();
                while self.token != token::Eof {
                    if let Some(item) = self.parse_foreign_item()? {
                        items.push(item);
                    }
                }
                Expansion::ForeignItems(items)
            }
815
            ExpansionKind::Stmts => {
816
                let mut stmts = SmallVector::new();
G
Geoffry Song 已提交
817 818 819
                while self.token != token::Eof &&
                      // won't make progress on a `}`
                      self.token != token::CloseDelim(token::Brace) {
J
Jeffrey Seyfried 已提交
820
                    if let Some(stmt) = self.parse_full_stmt(macro_legacy_warnings)? {
821 822 823 824 825 826
                        stmts.push(stmt);
                    }
                }
                Expansion::Stmts(stmts)
            }
            ExpansionKind::Expr => Expansion::Expr(self.parse_expr()?),
827 828 829 830 831 832 833
            ExpansionKind::OptExpr => {
                if self.token != token::Eof {
                    Expansion::OptExpr(Some(self.parse_expr()?))
                } else {
                    Expansion::OptExpr(None)
                }
            },
834
            ExpansionKind::Ty => Expansion::Ty(self.parse_ty()?),
835 836 837
            ExpansionKind::Pat => Expansion::Pat(self.parse_pat()?),
        })
    }
838

J
Jeffrey Seyfried 已提交
839
    pub fn ensure_complete_parse(&mut self, macro_path: &Path, kind_name: &str, span: Span) {
840 841 842
        if self.token != token::Eof {
            let msg = format!("macro expansion ignores token `{}` and any following",
                              self.this_token_to_string());
843 844
            // Avoid emitting backtrace info twice.
            let def_site_span = self.span.with_ctxt(SyntaxContext::empty());
845
            let mut err = self.diagnostic().struct_span_err(def_site_span, &msg);
846 847
            let msg = format!("caused by the macro expansion here; the usage \
                               of `{}!` is likely invalid in {} context",
J
Jeffrey Seyfried 已提交
848
                               macro_path, kind_name);
849 850 851
            err.span_note(span, &msg).emit();
        }
    }
852 853 854 855
}

struct InvocationCollector<'a, 'b: 'a> {
    cx: &'a mut ExtCtxt<'b>,
856
    cfg: StripUnconfigured<'a>,
857
    invocations: Vec<Invocation>,
858
    monotonic: bool,
859 860 861 862
}

impl<'a, 'b> InvocationCollector<'a, 'b> {
    fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
J
Jeffrey Seyfried 已提交
863
        let mark = Mark::fresh(self.cx.current_expansion.mark);
864
        self.invocations.push(Invocation {
865 866
            kind,
            expansion_kind,
J
Jeffrey Seyfried 已提交
867
            expansion_data: ExpansionData {
868
                mark,
J
Jeffrey Seyfried 已提交
869 870 871
                depth: self.cx.current_expansion.depth + 1,
                ..self.cx.current_expansion.clone()
            },
872
        });
873
        placeholder(expansion_kind, NodeId::placeholder_from_mark(mark))
874
    }
875

876 877
    fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: ExpansionKind) -> Expansion {
        self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
878
    }
879

880 881
    fn collect_attr(&mut self,
                    attr: Option<ast::Attribute>,
J
Jeffrey Seyfried 已提交
882
                    traits: Vec<Path>,
883 884
                    item: Annotatable,
                    kind: ExpansionKind)
885
                    -> Expansion {
886
        self.collect(kind, InvocationKind::Attr { attr, traits, item })
887 888 889
    }

    // If `item` is an attr invocation, remove and return the macro attribute.
J
Jeffrey Seyfried 已提交
890
    fn classify_item<T>(&mut self, mut item: T) -> (Option<ast::Attribute>, Vec<Path>, T)
891 892 893
        where T: HasAttrs,
    {
        let (mut attr, mut traits) = (None, Vec::new());
894

895
        item = item.map_attrs(|mut attrs| {
896 897 898 899
            if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs) {
                attr = Some(legacy_attr_invoc);
                return attrs;
            }
900

901 902 903 904
            if self.cx.ecfg.proc_macro_enabled() {
                attr = find_attr_invoc(&mut attrs);
            }
            traits = collect_derives(&mut self.cx, &mut attrs);
905 906
            attrs
        });
907

908
        (attr, traits, item)
909 910
    }

911 912 913
    fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
        self.cfg.configure(node)
    }
914 915 916 917 918 919

    // Detect use of feature-gated or invalid attributes on macro invocations
    // since they will not be detected after macro expansion.
    fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
        let features = self.cx.ecfg.features.unwrap();
        for attr in attrs.iter() {
920
            feature_gate::check_attribute(attr, self.cx.parse_sess, features);
921 922
        }
    }
923 924 925 926 927

    fn check_attribute(&mut self, at: &ast::Attribute) {
        let features = self.cx.ecfg.features.unwrap();
        feature_gate::check_attribute(at, self.cx.parse_sess, features);
    }
928 929
}

930
pub fn find_attr_invoc(attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
931 932 933
    attrs.iter()
         .position(|a| !attr::is_known(a) && !is_builtin_attr(a))
         .map(|i| attrs.remove(i))
934 935
}

936
impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
937
    fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
938
        let mut expr = self.cfg.configure_expr(expr).into_inner();
939 940
        expr.node = self.cfg.configure_expr_kind(expr.node);

941 942 943 944 945 946 947 948 949 950 951 952
        let (attr, derives, expr) = self.classify_item(expr);

        if attr.is_some() || !derives.is_empty() {
            // collect the invoc regardless of whether or not attributes are permitted here
            // expansion will eat the attribute so it won't error later
            attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));

            // ExpansionKind::Expr requires the macro to emit an expression
            return self.collect_attr(attr, derives, Annotatable::Expr(P(expr)), ExpansionKind::Expr)
                .make_expr();
        }

953
        if let ast::ExprKind::Mac(mac) = expr.node {
954 955
            self.check_attributes(&expr.attrs);
            self.collect_bang(mac, expr.span, ExpansionKind::Expr).make_expr()
956 957 958
        } else {
            P(noop_fold_expr(expr, self))
        }
959 960
    }

961
    fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
962
        let mut expr = configure!(self, expr).into_inner();
963 964
        expr.node = self.cfg.configure_expr_kind(expr.node);

965 966 967 968 969 970 971 972 973 974
        let (attr, derives, expr) = self.classify_item(expr);

        if attr.is_some() || !derives.is_empty() {
            attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));

            return self.collect_attr(attr, derives, Annotatable::Expr(P(expr)),
                                     ExpansionKind::OptExpr)
                .make_opt_expr();
        }

975
        if let ast::ExprKind::Mac(mac) = expr.node {
976 977
            self.check_attributes(&expr.attrs);
            self.collect_bang(mac, expr.span, ExpansionKind::OptExpr).make_opt_expr()
978 979 980
        } else {
            Some(P(noop_fold_expr(expr, self)))
        }
981 982
    }

983
    fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
984
        let pat = self.cfg.configure_pat(pat);
985 986
        match pat.node {
            PatKind::Mac(_) => {}
987
            _ => return noop_fold_pat(pat, self),
988
        }
K
Keegan McAllister 已提交
989

990
        pat.and_then(|pat| match pat.node {
991
            PatKind::Mac(mac) => self.collect_bang(mac, pat.span, ExpansionKind::Pat).make_pat(),
992 993
            _ => unreachable!(),
        })
994 995
    }

996
    fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
997
        let mut stmt = match self.cfg.configure_stmt(stmt) {
998
            Some(stmt) => stmt,
999
            None => return SmallVector::new(),
1000 1001
        };

1002 1003 1004 1005 1006 1007 1008 1009 1010
        // we'll expand attributes on expressions separately
        if !stmt.is_expr() {
            let (attr, derives, stmt_) = self.classify_item(stmt);

            if attr.is_some() || !derives.is_empty() {
                return self.collect_attr(attr, derives,
                                         Annotatable::Stmt(P(stmt_)), ExpansionKind::Stmts)
                    .make_stmts();
            }
1011

1012 1013
            stmt = stmt_;
        }
1014

1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
        if let StmtKind::Mac(mac) = stmt.node {
            let (mac, style, attrs) = mac.into_inner();
            self.check_attributes(&attrs);
            let mut placeholder = self.collect_bang(mac, stmt.span, ExpansionKind::Stmts)
                                        .make_stmts();

            // If this is a macro invocation with a semicolon, then apply that
            // semicolon to the final statement produced by expansion.
            if style == MacStmtStyle::Semicolon {
                if let Some(stmt) = placeholder.pop() {
                    placeholder.push(stmt.add_trailing_semicolon());
                }
1027
            }
1028 1029

            return placeholder;
1030 1031
        }

1032 1033 1034 1035 1036 1037
        // The placeholder expander gives ids to statements, so we avoid folding the id here.
        let ast::Stmt { id, node, span } = stmt;
        noop_fold_stmt_kind(node, self).into_iter().map(|node| {
            ast::Stmt { id, node, span }
        }).collect()

1038 1039
    }

S
Steven Fackler 已提交
1040
    fn fold_block(&mut self, block: P<Block>) -> P<Block> {
1041 1042
        let old_directory_ownership = self.cx.current_expansion.directory_ownership;
        self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
J
Jeffrey Seyfried 已提交
1043
        let result = noop_fold_block(block, self);
1044
        self.cx.current_expansion.directory_ownership = old_directory_ownership;
1045
        result
1046 1047
    }

1048
    fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
1049 1050
        let item = configure!(self, item);

1051 1052
        let (attr, traits, mut item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1053
            let item = Annotatable::Item(item);
1054
            return self.collect_attr(attr, traits, item, ExpansionKind::Items).make_items();
1055 1056 1057 1058
        }

        match item.node {
            ast::ItemKind::Mac(..) => {
1059
                self.check_attributes(&item.attrs);
1060
                item.and_then(|item| match item.node {
1061
                    ItemKind::Mac(mac) => {
1062
                        self.collect(ExpansionKind::Items, InvocationKind::Bang {
1063
                            mac,
1064 1065
                            ident: Some(item.ident),
                            span: item.span,
1066
                        }).make_items()
1067 1068 1069 1070 1071
                    }
                    _ => unreachable!(),
                })
            }
            ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
1072 1073 1074 1075
                if item.ident == keywords::Invalid.ident() {
                    return noop_fold_item(item, self);
                }

1076
                let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
1077 1078
                let mut module = (*self.cx.current_expansion.module).clone();
                module.mod_path.push(item.ident);
1079 1080 1081 1082

                // Detect if this is an inline module (`mod m { ... }` as opposed to `mod m;`).
                // In the non-inline case, `inner` is never the dummy span (c.f. `parse_item_mod`).
                // Thus, if `inner` is the dummy span, we know the module is inline.
J
Jeffrey Seyfried 已提交
1083
                let inline_module = item.span.contains(inner) || inner == DUMMY_SP;
1084 1085

                if inline_module {
1086
                    if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") {
1087 1088
                        self.cx.current_expansion.directory_ownership =
                            DirectoryOwnership::Owned { relative: None };
1089
                        module.directory.push(&*path.as_str());
1090 1091 1092
                    } else {
                        module.directory.push(&*item.ident.name.as_str());
                    }
1093
                } else {
1094 1095 1096 1097 1098
                    let path = self.cx.parse_sess.codemap().span_to_unmapped_path(inner);
                    let mut path = match path {
                        FileName::Real(path) => path,
                        other => PathBuf::from(other.to_string()),
                    };
1099
                    let directory_ownership = match path.file_name().unwrap().to_str() {
1100 1101 1102 1103 1104
                        Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
                        Some(_) => DirectoryOwnership::Owned {
                            relative: Some(item.ident),
                        },
                        None => DirectoryOwnership::UnownedViaMod(false),
1105 1106 1107 1108
                    };
                    path.pop();
                    module.directory = path;
                    self.cx.current_expansion.directory_ownership = directory_ownership;
1109 1110
                }

1111 1112
                let orig_module =
                    mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
J
Jeffrey Seyfried 已提交
1113
                let result = noop_fold_item(item, self);
1114
                self.cx.current_expansion.module = orig_module;
1115
                self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1116
                result
1117
            }
1118 1119 1120
            // Ensure that test functions are accessible from the test harness.
            ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
                if item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
1121 1122 1123 1124
                    item = item.map(|mut item| {
                        item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
                        item
                    });
1125 1126 1127
                }
                noop_fold_item(item, self)
            }
1128 1129
            _ => noop_fold_item(item, self),
        }
1130 1131
    }

1132
    fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector<ast::TraitItem> {
1133 1134
        let item = configure!(self, item);

1135 1136
        let (attr, traits, item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1137
            let item = Annotatable::TraitItem(P(item));
1138 1139
            return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems)
                .make_trait_items()
1140 1141 1142 1143 1144
        }

        match item.node {
            ast::TraitItemKind::Macro(mac) => {
                let ast::TraitItem { attrs, span, .. } = item;
1145 1146
                self.check_attributes(&attrs);
                self.collect_bang(mac, span, ExpansionKind::TraitItems).make_trait_items()
1147 1148 1149 1150 1151 1152
            }
            _ => fold::noop_fold_trait_item(item, self),
        }
    }

    fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVector<ast::ImplItem> {
1153 1154
        let item = configure!(self, item);

1155 1156
        let (attr, traits, item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1157
            let item = Annotatable::ImplItem(P(item));
1158 1159
            return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems)
                .make_impl_items();
1160 1161 1162 1163 1164
        }

        match item.node {
            ast::ImplItemKind::Macro(mac) => {
                let ast::ImplItem { attrs, span, .. } = item;
1165 1166
                self.check_attributes(&attrs);
                self.collect_bang(mac, span, ExpansionKind::ImplItems).make_impl_items()
1167
            }
1168
            _ => fold::noop_fold_impl_item(item, self),
1169
        }
1170 1171
    }

1172
    fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> {
1173
        let ty = match ty.node {
1174
            ast::TyKind::Mac(_) => ty.into_inner(),
1175 1176 1177 1178
            _ => return fold::noop_fold_ty(ty, self),
        };

        match ty.node {
1179
            ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, ExpansionKind::Ty).make_ty(),
1180 1181
            _ => unreachable!(),
        }
1182
    }
1183 1184 1185 1186 1187

    fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod {
        noop_fold_foreign_mod(self.cfg.configure_foreign_mod(foreign_mod), self)
    }

1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
    fn fold_foreign_item(&mut self,
                         foreign_item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> {
        let (attr, traits, foreign_item) = self.classify_item(foreign_item);

        let explain = if self.cx.ecfg.proc_macro_enabled() {
            feature_gate::EXPLAIN_PROC_MACROS_IN_EXTERN
        } else {
            feature_gate::EXPLAIN_MACROS_IN_EXTERN
        };

        if attr.is_some() || !traits.is_empty()  {
            if !self.cx.ecfg.macros_in_extern_enabled() {
                if let Some(ref attr) = attr {
                    emit_feature_err(&self.cx.parse_sess, "macros_in_extern", attr.span,
                                     GateIssue::Language, explain);
                }
            }

            let item = Annotatable::ForeignItem(P(foreign_item));
            return self.collect_attr(attr, traits, item, ExpansionKind::ForeignItems)
                .make_foreign_items();
        }

        if let ast::ForeignItemKind::Macro(mac) = foreign_item.node {
            self.check_attributes(&foreign_item.attrs);

            if !self.cx.ecfg.macros_in_extern_enabled() {
                emit_feature_err(&self.cx.parse_sess, "macros_in_extern", foreign_item.span,
                                 GateIssue::Language, explain);
            }

            return self.collect_bang(mac, foreign_item.span, ExpansionKind::ForeignItems)
                .make_foreign_items();
        }

        noop_fold_foreign_item(foreign_item, self)
    }

1226
    fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
1227 1228 1229 1230
        match item {
            ast::ItemKind::MacroDef(..) => item,
            _ => noop_fold_item_kind(self.cfg.configure_item_kind(item), self),
        }
1231
    }
1232

1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
    fn fold_attribute(&mut self, at: ast::Attribute) -> Option<ast::Attribute> {
        // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
        // contents="file contents")]` attributes
        if !at.check_name("doc") {
            return noop_fold_attribute(at, self);
        }

        if let Some(list) = at.meta_item_list() {
            if !list.iter().any(|it| it.check_name("include")) {
                return noop_fold_attribute(at, self);
            }

            let mut items = vec![];

            for it in list {
                if !it.check_name("include") {
                    items.push(noop_fold_meta_list_item(it, self));
                    continue;
                }

                if let Some(file) = it.value_str() {
                    let err_count = self.cx.parse_sess.span_diagnostic.err_count();
                    self.check_attribute(&at);
                    if self.cx.parse_sess.span_diagnostic.err_count() > err_count {
                        // avoid loading the file if they haven't enabled the feature
                        return noop_fold_attribute(at, self);
                    }

                    let mut buf = vec![];
                    let filename = self.cx.root_path.join(file.to_string());

                    match File::open(&filename).and_then(|mut f| f.read_to_end(&mut buf)) {
                        Ok(..) => {}
                        Err(e) => {
1267 1268 1269 1270
                            self.cx.span_err(at.span,
                                             &format!("couldn't read {}: {}",
                                                      filename.display(),
                                                      e));
1271 1272 1273 1274 1275
                        }
                    }

                    match String::from_utf8(buf) {
                        Ok(src) => {
1276 1277 1278 1279
                            // Add this input file to the code map to make it available as
                            // dependency information
                            self.cx.codemap().new_filemap_and_lines(&filename, &src);

1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292
                            let include_info = vec![
                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
                                        attr::mk_name_value_item_str("file".into(),
                                                                     file))),
                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
                                        attr::mk_name_value_item_str("contents".into(),
                                                                     (&*src).into()))),
                            ];

                            items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(
                                        attr::mk_list_item("include".into(), include_info))));
                        }
                        Err(_) => {
1293 1294 1295
                            self.cx.span_err(at.span,
                                             &format!("{} wasn't a utf-8 file",
                                                      filename.display()));
1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314
                        }
                    }
                } else {
                    items.push(noop_fold_meta_list_item(it, self));
                }
            }

            let meta = attr::mk_list_item("doc".into(), items);
            match at.style {
                ast::AttrStyle::Inner =>
                    Some(attr::mk_spanned_attr_inner(at.span, at.id, meta)),
                ast::AttrStyle::Outer =>
                    Some(attr::mk_spanned_attr_outer(at.span, at.id, meta)),
            }
        } else {
            noop_fold_attribute(at, self)
        }
    }

1315
    fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
1316 1317 1318 1319 1320 1321
        if self.monotonic {
            assert_eq!(id, ast::DUMMY_NODE_ID);
            self.cx.resolver.next_node_id()
        } else {
            id
        }
1322
    }
1323 1324
}

1325
pub struct ExpansionConfig<'feat> {
1326
    pub crate_name: String,
1327
    pub features: Option<&'feat Features>,
P
Paul Collier 已提交
1328
    pub recursion_limit: usize,
1329
    pub trace_mac: bool,
1330
    pub should_test: bool, // If false, strip `#[test]` nodes
1331 1332
    pub single_step: bool,
    pub keep_macs: bool,
1333 1334
}

1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
macro_rules! feature_tests {
    ($( fn $getter:ident = $field:ident, )*) => {
        $(
            pub fn $getter(&self) -> bool {
                match self.features {
                    Some(&Features { $field: true, .. }) => true,
                    _ => false,
                }
            }
        )*
    }
}

1348 1349
impl<'feat> ExpansionConfig<'feat> {
    pub fn default(crate_name: String) -> ExpansionConfig<'static> {
1350
        ExpansionConfig {
1351
            crate_name,
1352
            features: None,
1353
            recursion_limit: 1024,
1354
            trace_mac: false,
1355
            should_test: false,
1356 1357
            single_step: false,
            keep_macs: false,
1358 1359
        }
    }
1360

1361
    feature_tests! {
1362 1363
        fn enable_quotes = quote,
        fn enable_asm = asm,
1364
        fn enable_global_asm = global_asm,
1365 1366 1367
        fn enable_log_syntax = log_syntax,
        fn enable_concat_idents = concat_idents,
        fn enable_trace_macros = trace_macros,
1368
        fn enable_allow_internal_unstable = allow_internal_unstable,
1369
        fn enable_custom_derive = custom_derive,
1370
        fn proc_macro_enabled = proc_macro,
1371
        fn macros_in_extern_enabled = macros_in_extern,
1372
    }
1373 1374
}

1375
// A Marker adds the given mark to the syntax context.
1376
#[derive(Debug)]
1377
pub struct Marker(pub Mark);
1378

E
Eduard Burtescu 已提交
1379
impl Folder for Marker {
1380
    fn fold_ident(&mut self, mut ident: Ident) -> Ident {
1381
        ident.span = ident.span.apply_mark(self.0);
1382 1383
        ident
    }
1384

1385 1386
    fn new_span(&mut self, span: Span) -> Span {
        span.with_ctxt(span.ctxt().apply_mark(self.0))
1387
    }
1388 1389 1390 1391

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