Skip to content

Commit 7408ffd

Browse files
author
Keegan McAllister
committed
---
yaml --- r: 180950 b: refs/heads/snap-stage3 c: 6864792 h: refs/heads/master v: v3
1 parent 8921eba commit 7408ffd

File tree

5 files changed

+206
-172
lines changed

5 files changed

+206
-172
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: c5db290bf6df986a6acd5ce993f278c18e55ca37
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 6b784bacbfb3135bd34cd994023ac1e841ad9ceb
4+
refs/heads/snap-stage3: 6864792df002a4430634ea6ae096dd7e524560c2
55
refs/heads/try: ccf8fedf1cffcb8f6f3581d53d220039e192fe77
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Used by `rustc` when loading a crate with exported macros.
12+
13+
use session::Session;
14+
use metadata::creader::CrateReader;
15+
16+
use std::collections::{HashSet, HashMap};
17+
use syntax::ast;
18+
use syntax::attr;
19+
use syntax::codemap::Span;
20+
use syntax::parse::token;
21+
use syntax::visit;
22+
use syntax::visit::Visitor;
23+
use syntax::attr::AttrMetaMethods;
24+
25+
struct MacroLoader<'a> {
26+
sess: &'a Session,
27+
span_whitelist: HashSet<Span>,
28+
reader: CrateReader<'a>,
29+
macros: Vec<ast::MacroDef>,
30+
}
31+
32+
impl<'a> MacroLoader<'a> {
33+
fn new(sess: &'a Session) -> MacroLoader<'a> {
34+
MacroLoader {
35+
sess: sess,
36+
span_whitelist: HashSet::new(),
37+
reader: CrateReader::new(sess),
38+
macros: vec![],
39+
}
40+
}
41+
}
42+
43+
/// Read exported macros.
44+
pub fn read_macro_defs(sess: &Session, krate: &ast::Crate) -> Vec<ast::MacroDef> {
45+
let mut loader = MacroLoader::new(sess);
46+
47+
// We need to error on `#[macro_use] extern crate` when it isn't at the
48+
// crate root, because `$crate` won't work properly. Identify these by
49+
// spans, because the crate map isn't set up yet.
50+
for item in &krate.module.items {
51+
if let ast::ItemExternCrate(_) = item.node {
52+
loader.span_whitelist.insert(item.span);
53+
}
54+
}
55+
56+
visit::walk_crate(&mut loader, krate);
57+
58+
loader.macros
59+
}
60+
61+
pub type MacroSelection = HashMap<token::InternedString, Span>;
62+
63+
// note that macros aren't expanded yet, and therefore macros can't add macro imports.
64+
impl<'a, 'v> Visitor<'v> for MacroLoader<'a> {
65+
fn visit_item(&mut self, item: &ast::Item) {
66+
// We're only interested in `extern crate`.
67+
match item.node {
68+
ast::ItemExternCrate(_) => {}
69+
_ => {
70+
visit::walk_item(self, item);
71+
return;
72+
}
73+
}
74+
75+
// Parse the attributes relating to macros.
76+
let mut import = Some(HashMap::new()); // None => load all
77+
let mut reexport = HashMap::new();
78+
79+
for attr in &item.attrs {
80+
let mut used = true;
81+
match &attr.name()[] {
82+
"phase" => {
83+
self.sess.span_err(attr.span, "#[phase] is deprecated");
84+
}
85+
"plugin" => {
86+
self.sess.span_err(attr.span, "#[plugin] on `extern crate` is deprecated");
87+
self.sess.span_help(attr.span, &format!("use a crate attribute instead, \
88+
i.e. #![plugin({})]",
89+
item.ident.as_str())[]);
90+
}
91+
"macro_use" => {
92+
let names = attr.meta_item_list();
93+
if names.is_none() {
94+
// no names => load all
95+
import = None;
96+
}
97+
if let (Some(sel), Some(names)) = (import.as_mut(), names) {
98+
for attr in names {
99+
if let ast::MetaWord(ref name) = attr.node {
100+
sel.insert(name.clone(), attr.span);
101+
} else {
102+
self.sess.span_err(attr.span, "bad macro import");
103+
}
104+
}
105+
}
106+
}
107+
"macro_reexport" => {
108+
let names = match attr.meta_item_list() {
109+
Some(names) => names,
110+
None => {
111+
self.sess.span_err(attr.span, "bad macro reexport");
112+
continue;
113+
}
114+
};
115+
116+
for attr in names {
117+
if let ast::MetaWord(ref name) = attr.node {
118+
reexport.insert(name.clone(), attr.span);
119+
} else {
120+
self.sess.span_err(attr.span, "bad macro reexport");
121+
}
122+
}
123+
}
124+
_ => used = false,
125+
}
126+
if used {
127+
attr::mark_used(attr);
128+
}
129+
}
130+
131+
self.load_macros(item, import, reexport)
132+
}
133+
134+
fn visit_mac(&mut self, _: &ast::Mac) {
135+
// bummer... can't see macro imports inside macros.
136+
// do nothing.
137+
}
138+
}
139+
140+
impl<'a> MacroLoader<'a> {
141+
fn load_macros<'b>(&mut self,
142+
vi: &ast::Item,
143+
import: Option<MacroSelection>,
144+
reexport: MacroSelection) {
145+
if let Some(sel) = import.as_ref() {
146+
if sel.is_empty() && reexport.is_empty() {
147+
return;
148+
}
149+
}
150+
151+
if !self.span_whitelist.contains(&vi.span) {
152+
self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
153+
the crate root");
154+
return;
155+
}
156+
157+
let macros = self.reader.read_exported_macros(vi);
158+
let mut seen = HashSet::new();
159+
160+
for mut def in macros {
161+
let name = token::get_ident(def.ident);
162+
seen.insert(name.clone());
163+
164+
def.use_locally = match import.as_ref() {
165+
None => true,
166+
Some(sel) => sel.contains_key(&name),
167+
};
168+
def.export = reexport.contains_key(&name);
169+
self.macros.push(def);
170+
}
171+
172+
if let Some(sel) = import.as_ref() {
173+
for (name, span) in sel.iter() {
174+
if !seen.contains(name) {
175+
self.sess.span_err(*span, "imported macro not found");
176+
}
177+
}
178+
}
179+
180+
for (name, span) in reexport.iter() {
181+
if !seen.contains(name) {
182+
self.sess.span_err(*span, "reexported macro not found");
183+
}
184+
}
185+
}
186+
}

branches/snap-stage3/src/librustc/metadata/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ pub mod cstore;
1818
pub mod csearch;
1919
pub mod loader;
2020
pub mod filesearch;
21+
pub mod macro_import;

0 commit comments

Comments
 (0)