commit
a4a249fcab
10 changed files with 221 additions and 11 deletions
|
@ -30,7 +30,7 @@ use rustc_back::target::Target;
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
@ -77,6 +77,11 @@ pub struct Session {
|
||||||
/// available in this crate
|
/// available in this crate
|
||||||
pub available_macros: RefCell<HashSet<Name>>,
|
pub available_macros: RefCell<HashSet<Name>>,
|
||||||
|
|
||||||
|
/// Map from imported macro spans (which consist of
|
||||||
|
/// the localized span for the macro body) to the
|
||||||
|
/// macro name and defintion span in the source crate.
|
||||||
|
pub imported_macro_spans: RefCell<HashMap<Span, (String, Span)>>,
|
||||||
|
|
||||||
next_node_id: Cell<ast::NodeId>,
|
next_node_id: Cell<ast::NodeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,6 +484,7 @@ pub fn build_session_(sopts: config::Options,
|
||||||
next_node_id: Cell::new(1),
|
next_node_id: Cell::new(1),
|
||||||
injected_allocator: Cell::new(None),
|
injected_allocator: Cell::new(None),
|
||||||
available_macros: RefCell::new(HashSet::new()),
|
available_macros: RefCell::new(HashSet::new()),
|
||||||
|
imported_macro_spans: RefCell::new(HashMap::new()),
|
||||||
};
|
};
|
||||||
|
|
||||||
sess
|
sess
|
||||||
|
|
|
@ -223,6 +223,8 @@ pub const tag_polarity: usize = 0x9d;
|
||||||
pub const tag_macro_defs: usize = 0x10e; // top-level only
|
pub const tag_macro_defs: usize = 0x10e; // top-level only
|
||||||
pub const tag_macro_def: usize = 0x9e;
|
pub const tag_macro_def: usize = 0x9e;
|
||||||
pub const tag_macro_def_body: usize = 0x9f;
|
pub const tag_macro_def_body: usize = 0x9f;
|
||||||
|
pub const tag_macro_def_span_lo: usize = 0xa8;
|
||||||
|
pub const tag_macro_def_span_hi: usize = 0xa9;
|
||||||
|
|
||||||
pub const tag_paren_sugar: usize = 0xa0;
|
pub const tag_paren_sugar: usize = 0xa0;
|
||||||
|
|
||||||
|
|
|
@ -494,7 +494,7 @@ impl<'a> CrateReader<'a> {
|
||||||
let mut macros = vec![];
|
let mut macros = vec![];
|
||||||
decoder::each_exported_macro(ekrate.metadata.as_slice(),
|
decoder::each_exported_macro(ekrate.metadata.as_slice(),
|
||||||
&*self.cstore.intr,
|
&*self.cstore.intr,
|
||||||
|name, attrs, body| {
|
|name, attrs, span, body| {
|
||||||
// NB: Don't use parse::parse_tts_from_source_str because it parses with
|
// NB: Don't use parse::parse_tts_from_source_str because it parses with
|
||||||
// quote_depth > 0.
|
// quote_depth > 0.
|
||||||
let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess,
|
let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess,
|
||||||
|
@ -509,7 +509,7 @@ impl<'a> CrateReader<'a> {
|
||||||
panic!(FatalError);
|
panic!(FatalError);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let span = mk_sp(lo, p.last_span.hi);
|
let local_span = mk_sp(lo, p.last_span.hi);
|
||||||
|
|
||||||
// Mark the attrs as used
|
// Mark the attrs as used
|
||||||
for attr in &attrs {
|
for attr in &attrs {
|
||||||
|
@ -520,7 +520,7 @@ impl<'a> CrateReader<'a> {
|
||||||
ident: ast::Ident::with_empty_ctxt(name),
|
ident: ast::Ident::with_empty_ctxt(name),
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
span: span,
|
span: local_span,
|
||||||
imported_from: Some(item.ident),
|
imported_from: Some(item.ident),
|
||||||
// overridden in plugin/load.rs
|
// overridden in plugin/load.rs
|
||||||
export: false,
|
export: false,
|
||||||
|
@ -529,6 +529,8 @@ impl<'a> CrateReader<'a> {
|
||||||
|
|
||||||
body: body,
|
body: body,
|
||||||
});
|
});
|
||||||
|
self.sess.imported_macro_spans.borrow_mut()
|
||||||
|
.insert(local_span, (name.as_str().to_string(), span));
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -52,7 +52,7 @@ use syntax::parse::token::{IdentInterner, special_idents};
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
use syntax::codemap::{self, Span};
|
use syntax::codemap::{self, Span, BytePos, NO_EXPANSION};
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
|
|
||||||
|
@ -1471,19 +1471,28 @@ pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<DefIndex> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
|
pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
|
||||||
F: FnMut(ast::Name, Vec<ast::Attribute>, String) -> bool,
|
F: FnMut(ast::Name, Vec<ast::Attribute>, Span, String) -> bool,
|
||||||
{
|
{
|
||||||
let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs);
|
let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs);
|
||||||
for macro_doc in reader::tagged_docs(macros, tag_macro_def) {
|
for macro_doc in reader::tagged_docs(macros, tag_macro_def) {
|
||||||
let name = item_name(intr, macro_doc);
|
let name = item_name(intr, macro_doc);
|
||||||
let attrs = get_attributes(macro_doc);
|
let attrs = get_attributes(macro_doc);
|
||||||
|
let span = get_macro_span(macro_doc);
|
||||||
let body = reader::get_doc(macro_doc, tag_macro_def_body);
|
let body = reader::get_doc(macro_doc, tag_macro_def_body);
|
||||||
if !f(name, attrs, body.as_str().to_string()) {
|
if !f(name, attrs, span, body.as_str().to_string()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_macro_span(doc: rbml::Doc) -> Span {
|
||||||
|
let lo_doc = reader::get_doc(doc, tag_macro_def_span_lo);
|
||||||
|
let lo = BytePos(reader::doc_as_u32(lo_doc));
|
||||||
|
let hi_doc = reader::get_doc(doc, tag_macro_def_span_hi);
|
||||||
|
let hi = BytePos(reader::doc_as_u32(hi_doc));
|
||||||
|
return Span { lo: lo, hi: hi, expn_id: NO_EXPANSION };
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_dylib_dependency_formats(cdata: Cmd)
|
pub fn get_dylib_dependency_formats(cdata: Cmd)
|
||||||
-> Vec<(ast::CrateNum, LinkagePreference)>
|
-> Vec<(ast::CrateNum, LinkagePreference)>
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,7 @@ use std::rc::Rc;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
|
use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
|
||||||
|
use syntax::codemap::BytePos;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::attr::AttrMetaMethods;
|
use syntax::attr::AttrMetaMethods;
|
||||||
use syntax::errors::Handler;
|
use syntax::errors::Handler;
|
||||||
|
@ -1727,6 +1728,10 @@ fn encode_macro_defs(rbml_w: &mut Encoder,
|
||||||
|
|
||||||
encode_name(rbml_w, def.name);
|
encode_name(rbml_w, def.name);
|
||||||
encode_attributes(rbml_w, &def.attrs);
|
encode_attributes(rbml_w, &def.attrs);
|
||||||
|
let &BytePos(lo) = &def.span.lo;
|
||||||
|
let &BytePos(hi) = &def.span.hi;
|
||||||
|
rbml_w.wr_tagged_u32(tag_macro_def_span_lo, lo);
|
||||||
|
rbml_w.wr_tagged_u32(tag_macro_def_span_hi, hi);
|
||||||
|
|
||||||
rbml_w.wr_tagged_str(tag_macro_def_body,
|
rbml_w.wr_tagged_str(tag_macro_def_body,
|
||||||
&::syntax::print::pprust::tts_to_string(&def.body));
|
&::syntax::print::pprust::tts_to_string(&def.body));
|
||||||
|
|
|
@ -37,6 +37,8 @@ use middle::def_id::DefId;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::hash::*;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use syntax::ast::{self, NodeId};
|
use syntax::ast::{self, NodeId};
|
||||||
use syntax::codemap::*;
|
use syntax::codemap::*;
|
||||||
|
@ -70,6 +72,14 @@ pub struct DumpCsvVisitor<'l, 'tcx: 'l> {
|
||||||
fmt: FmtStrs<'l, 'tcx>,
|
fmt: FmtStrs<'l, 'tcx>,
|
||||||
|
|
||||||
cur_scope: NodeId,
|
cur_scope: NodeId,
|
||||||
|
|
||||||
|
// Set of macro definition (callee) spans, and the set
|
||||||
|
// of macro use (callsite) spans. We store these to ensure
|
||||||
|
// we only write one macro def per unique macro definition, and
|
||||||
|
// one macro use per unique callsite span.
|
||||||
|
mac_defs: HashSet<Span>,
|
||||||
|
mac_uses: HashSet<Span>,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||||
|
@ -92,6 +102,8 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||||
span_utils,
|
span_utils,
|
||||||
tcx),
|
tcx),
|
||||||
cur_scope: 0,
|
cur_scope: 0,
|
||||||
|
mac_defs: HashSet::new(),
|
||||||
|
mac_uses: HashSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,10 +826,41 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||||
&typ);
|
&typ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract macro use and definition information from the AST node defined
|
||||||
|
/// by the given NodeId, using the expansion information from the node's
|
||||||
|
/// span.
|
||||||
|
///
|
||||||
|
/// If the span is not macro-generated, do nothing, else use callee and
|
||||||
|
/// callsite spans to record macro definition and use data, using the
|
||||||
|
/// mac_uses and mac_defs sets to prevent multiples.
|
||||||
|
fn process_macro_use(&mut self, span: Span, id: NodeId) {
|
||||||
|
let data = match self.save_ctxt.get_macro_use_data(span, id) {
|
||||||
|
None => return,
|
||||||
|
Some(data) => data,
|
||||||
|
};
|
||||||
|
let mut hasher = SipHasher::new();
|
||||||
|
data.callee_span.hash(&mut hasher);
|
||||||
|
let hash = hasher.finish();
|
||||||
|
let qualname = format!("{}::{}", data.name, hash);
|
||||||
|
// Don't write macro definition for imported macros
|
||||||
|
if !self.mac_defs.contains(&data.callee_span)
|
||||||
|
&& !data.imported {
|
||||||
|
self.mac_defs.insert(data.callee_span);
|
||||||
|
self.fmt.macro_str(data.callee_span, data.callee_span,
|
||||||
|
data.name.clone(), qualname.clone());
|
||||||
|
}
|
||||||
|
if !self.mac_uses.contains(&data.span) {
|
||||||
|
self.mac_uses.insert(data.span);
|
||||||
|
self.fmt.macro_use_str(data.span, data.span, data.name,
|
||||||
|
qualname, data.scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||||
fn visit_item(&mut self, item: &ast::Item) {
|
fn visit_item(&mut self, item: &ast::Item) {
|
||||||
|
self.process_macro_use(item.span, item.id);
|
||||||
match item.node {
|
match item.node {
|
||||||
ast::ItemUse(ref use_item) => {
|
ast::ItemUse(ref use_item) => {
|
||||||
match use_item.node {
|
match use_item.node {
|
||||||
|
@ -970,6 +1013,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
|
fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
|
||||||
|
self.process_macro_use(trait_item.span, trait_item.id);
|
||||||
match trait_item.node {
|
match trait_item.node {
|
||||||
ast::ConstTraitItem(ref ty, Some(ref expr)) => {
|
ast::ConstTraitItem(ref ty, Some(ref expr)) => {
|
||||||
self.process_const(trait_item.id,
|
self.process_const(trait_item.id,
|
||||||
|
@ -991,6 +1035,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
|
fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
|
||||||
|
self.process_macro_use(impl_item.span, impl_item.id);
|
||||||
match impl_item.node {
|
match impl_item.node {
|
||||||
ast::ImplItemKind::Const(ref ty, ref expr) => {
|
ast::ImplItemKind::Const(ref ty, ref expr) => {
|
||||||
self.process_const(impl_item.id,
|
self.process_const(impl_item.id,
|
||||||
|
@ -1012,6 +1057,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, t: &ast::Ty) {
|
fn visit_ty(&mut self, t: &ast::Ty) {
|
||||||
|
self.process_macro_use(t.span, t.id);
|
||||||
match t.node {
|
match t.node {
|
||||||
ast::TyPath(_, ref path) => {
|
ast::TyPath(_, ref path) => {
|
||||||
match self.lookup_type_ref(t.id) {
|
match self.lookup_type_ref(t.id) {
|
||||||
|
@ -1031,6 +1077,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, ex: &ast::Expr) {
|
fn visit_expr(&mut self, ex: &ast::Expr) {
|
||||||
|
self.process_macro_use(ex.span, ex.id);
|
||||||
match ex.node {
|
match ex.node {
|
||||||
ast::ExprCall(ref _f, ref _args) => {
|
ast::ExprCall(ref _f, ref _args) => {
|
||||||
// Don't need to do anything for function calls,
|
// Don't need to do anything for function calls,
|
||||||
|
@ -1117,11 +1164,13 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_mac(&mut self, _: &ast::Mac) {
|
fn visit_mac(&mut self, mac: &ast::Mac) {
|
||||||
// Just stop, macros are poison to us.
|
// These shouldn't exist in the AST at this point, log a span bug.
|
||||||
|
self.sess.span_bug(mac.span, "macro invocation should have been expanded out of AST");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_pat(&mut self, p: &ast::Pat) {
|
fn visit_pat(&mut self, p: &ast::Pat) {
|
||||||
|
self.process_macro_use(p.span, p.id);
|
||||||
self.process_pat(p);
|
self.process_pat(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1177,10 +1226,13 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_stmt(&mut self, s: &ast::Stmt) {
|
fn visit_stmt(&mut self, s: &ast::Stmt) {
|
||||||
|
let id = s.node.id();
|
||||||
|
self.process_macro_use(s.span, id.unwrap());
|
||||||
visit::walk_stmt(self, s)
|
visit::walk_stmt(self, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_local(&mut self, l: &ast::Local) {
|
fn visit_local(&mut self, l: &ast::Local) {
|
||||||
|
self.process_macro_use(l.span, l.id);
|
||||||
let value = self.span.snippet(l.span);
|
let value = self.span.snippet(l.span);
|
||||||
self.process_var_decl(&l.pat, value);
|
self.process_var_decl(&l.pat, value);
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,8 @@ pub enum Data {
|
||||||
FunctionCallData(FunctionCallData),
|
FunctionCallData(FunctionCallData),
|
||||||
/// Data about a method call.
|
/// Data about a method call.
|
||||||
MethodCallData(MethodCallData),
|
MethodCallData(MethodCallData),
|
||||||
|
/// Data about a macro use.
|
||||||
|
MacroUseData(MacroUseData),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data for all kinds of functions and methods.
|
/// Data for all kinds of functions and methods.
|
||||||
|
@ -174,6 +176,22 @@ pub struct MethodCallData {
|
||||||
pub decl_id: Option<DefId>,
|
pub decl_id: Option<DefId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Data about a macro use.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MacroUseData {
|
||||||
|
pub span: Span,
|
||||||
|
pub name: String,
|
||||||
|
// Because macro expansion happens before ref-ids are determined,
|
||||||
|
// we use the callee span to reference the associated macro definition.
|
||||||
|
pub callee_span: Span,
|
||||||
|
pub scope: NodeId,
|
||||||
|
pub imported: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! option_try(
|
||||||
|
($e:expr) => (match $e { Some(e) => e, None => return None })
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||||
|
@ -655,6 +673,51 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempt to return MacroUseData for any AST node.
|
||||||
|
///
|
||||||
|
/// For a given piece of AST defined by the supplied Span and NodeId,
|
||||||
|
/// returns None if the node is not macro-generated or the span is malformed,
|
||||||
|
/// else uses the expansion callsite and callee to return some MacroUseData.
|
||||||
|
pub fn get_macro_use_data(&self, span: Span, id: NodeId) -> Option<MacroUseData> {
|
||||||
|
if !generated_code(span) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
// Note we take care to use the source callsite/callee, to handle
|
||||||
|
// nested expansions and ensure we only generate data for source-visible
|
||||||
|
// macro uses.
|
||||||
|
let callsite = self.tcx.sess.codemap().source_callsite(span);
|
||||||
|
let callee = self.tcx.sess.codemap().source_callee(span);
|
||||||
|
let callee = option_try!(callee);
|
||||||
|
let callee_span = option_try!(callee.span);
|
||||||
|
|
||||||
|
// Ignore attribute macros, their spans are usually mangled
|
||||||
|
if let MacroAttribute(_) = callee.format {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the callee is an imported macro from an external crate, need to get
|
||||||
|
// the source span and name from the session, as their spans are localized
|
||||||
|
// when read in, and no longer correspond to the source.
|
||||||
|
if let Some(mac) = self.tcx.sess.imported_macro_spans.borrow().get(&callee_span) {
|
||||||
|
let &(ref mac_name, mac_span) = mac;
|
||||||
|
return Some(MacroUseData {
|
||||||
|
span: callsite,
|
||||||
|
name: mac_name.clone(),
|
||||||
|
callee_span: mac_span,
|
||||||
|
scope: self.enclosing_scope(id),
|
||||||
|
imported: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(MacroUseData {
|
||||||
|
span: callsite,
|
||||||
|
name: callee.name().to_string(),
|
||||||
|
callee_span: callee_span,
|
||||||
|
scope: self.enclosing_scope(id),
|
||||||
|
imported: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_data_for_id(&self, _id: &NodeId) -> Data {
|
pub fn get_data_for_id(&self, _id: &NodeId) -> Data {
|
||||||
// FIXME
|
// FIXME
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
|
|
|
@ -96,6 +96,8 @@ pub enum Row {
|
||||||
VarRef,
|
VarRef,
|
||||||
TypeRef,
|
TypeRef,
|
||||||
FnRef,
|
FnRef,
|
||||||
|
Macro,
|
||||||
|
MacroUse,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx: 'a> FmtStrs<'a, 'tcx> {
|
impl<'a, 'tcx: 'a> FmtStrs<'a, 'tcx> {
|
||||||
|
@ -219,6 +221,14 @@ impl<'a, 'tcx: 'a> FmtStrs<'a, 'tcx> {
|
||||||
vec!("refid", "refidcrate", "qualname", "scopeid"),
|
vec!("refid", "refidcrate", "qualname", "scopeid"),
|
||||||
true,
|
true,
|
||||||
true),
|
true),
|
||||||
|
Macro => ("macro",
|
||||||
|
vec!("name", "qualname"),
|
||||||
|
true,
|
||||||
|
true),
|
||||||
|
MacroUse => ("macro_use",
|
||||||
|
vec!("callee_name", "qualname", "scopeid"),
|
||||||
|
true,
|
||||||
|
true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,4 +696,19 @@ impl<'a, 'tcx: 'a> FmtStrs<'a, 'tcx> {
|
||||||
sub_span,
|
sub_span,
|
||||||
svec!(id.index.as_usize(), id.krate, "", scope_id));
|
svec!(id.index.as_usize(), id.krate, "", scope_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn macro_str(&mut self, span: Span, sub_span: Span, name: String, qualname: String) {
|
||||||
|
self.record_with_span(Macro, span, sub_span, svec!(name, qualname));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn macro_use_str(&mut self,
|
||||||
|
span: Span,
|
||||||
|
sub_span: Span,
|
||||||
|
name: String,
|
||||||
|
qualname: String,
|
||||||
|
scope_id: NodeId) {
|
||||||
|
let scope_id = self.normalize_node_id(scope_id);
|
||||||
|
self.record_with_span(MacroUse, span, sub_span,
|
||||||
|
svec!(name, qualname, scope_id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -378,6 +378,25 @@ impl<'a> SpanUtils<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Given a macro_rules definition span, return the span of the macro's name.
|
||||||
|
pub fn span_for_macro_name(&self, span: Span) -> Option<Span> {
|
||||||
|
let mut toks = self.retokenise_span(span);
|
||||||
|
loop {
|
||||||
|
let ts = toks.real_token();
|
||||||
|
if ts.tok == token::Eof {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if ts.tok == token::Not {
|
||||||
|
let ts = toks.real_token();
|
||||||
|
if ts.tok.is_ident() {
|
||||||
|
return self.make_sub_span(span, Some(ts.sp));
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return true if the span is generated code, and
|
/// Return true if the span is generated code, and
|
||||||
/// it is not a subspan of the root callsite.
|
/// it is not a subspan of the root callsite.
|
||||||
///
|
///
|
||||||
|
@ -395,10 +414,16 @@ impl<'a> SpanUtils<'a> {
|
||||||
if sub_span.is_none() {
|
if sub_span.is_none() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// A generated span is deemed invalid if it is not a sub-span of the root
|
|
||||||
|
//If the span comes from a fake filemap, filter it.
|
||||||
|
if !self.sess.codemap().lookup_char_pos(parent.lo).file.is_real_file() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, a generated span is deemed invalid if it is not a sub-span of the root
|
||||||
// callsite. This filters out macro internal variables and most malformed spans.
|
// callsite. This filters out macro internal variables and most malformed spans.
|
||||||
let span = self.sess.codemap().source_callsite(parent);
|
let span = self.sess.codemap().source_callsite(parent);
|
||||||
!(parent.lo >= span.lo && parent.hi <= span.hi)
|
!(span.contains(parent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1064,6 +1064,27 @@ impl CodeMap {
|
||||||
span
|
span
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the source callee.
|
||||||
|
///
|
||||||
|
/// Returns None if the supplied span has no expansion trace,
|
||||||
|
/// else returns the NameAndSpan for the macro definition
|
||||||
|
/// corresponding to the source callsite.
|
||||||
|
pub fn source_callee(&self, sp: Span) -> Option<NameAndSpan> {
|
||||||
|
let mut span = sp;
|
||||||
|
while let Some(callsite) = self.with_expn_info(span.expn_id,
|
||||||
|
|ei| ei.map(|ei| ei.call_site.clone())) {
|
||||||
|
if let Some(_) = self.with_expn_info(callsite.expn_id,
|
||||||
|
|ei| ei.map(|ei| ei.call_site.clone())) {
|
||||||
|
span = callsite;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return self.with_expn_info(span.expn_id,
|
||||||
|
|ei| ei.map(|ei| ei.callee.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn span_to_filename(&self, sp: Span) -> FileName {
|
pub fn span_to_filename(&self, sp: Span) -> FileName {
|
||||||
self.lookup_char_pos(sp.lo).file.name.to_string()
|
self.lookup_char_pos(sp.lo).file.name.to_string()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue