More strict macro check

This commit is contained in:
Andre Bogus
2015-09-06 10:53:55 +02:00
parent 8be8d84fa0
commit 54393f0ef5
6 changed files with 71 additions and 69 deletions

View File

@@ -14,40 +14,51 @@ pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"];
pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"];
pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"];
/// returns true if the macro that expanded the crate was outside of
/// the current crate or was a compiler plugin
pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool {
// no ExpnInfo = no macro
opt_info.map_or(false, |info| {
match info.callee.format {
ExpnFormat::CompilerExpansion(..) => {
if info.callee.name() == "closure expansion" {
return false;
}
},
ExpnFormat::MacroAttribute(..) => {
// these are all plugins
return true;
},
_ => (),
/// returns true this expn_info was expanded by any macro
pub fn in_macro(cx: &Context, span: Span) -> bool {
cx.sess().codemap().with_expn_info(span.expn_id,
|info| info.map_or(false, |i| {
match i.callee.format {
ExpnFormat::CompilerExpansion(..) => false,
_ => true,
}
// no span for the callee = external macro
info.callee.span.map_or(true, |span| {
// no snippet = external macro or compiler-builtin expansion
cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code|
// macro doesn't start with "macro_rules"
// = compiler plugin
!code.starts_with("macro_rules")
)
})
})
}))
}
/// invokes in_macro with the expansion info of the given span
/// slightly heavy, try to use this after other checks have already happened
/// returns true if the macro that expanded the crate was outside of
/// the current crate or was a compiler plugin
pub fn in_external_macro(cx: &Context, span: Span) -> bool {
/// invokes in_macro with the expansion info of the given span
/// slightly heavy, try to use this after other checks have already happened
fn in_macro_ext(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool {
// no ExpnInfo = no macro
opt_info.map_or(false, |info| {
match info.callee.format {
ExpnFormat::CompilerExpansion(..) => {
if info.callee.name() == "closure expansion" {
return false;
}
},
ExpnFormat::MacroAttribute(..) => {
// these are all plugins
return true;
},
_ => (),
}
// no span for the callee = external macro
info.callee.span.map_or(true, |span| {
// no snippet = external macro or compiler-builtin expansion
cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code|
// macro doesn't start with "macro_rules"
// = compiler plugin
!code.starts_with("macro_rules")
)
})
})
}
cx.sess().codemap().with_expn_info(span.expn_id,
|info| in_macro(cx, info))
|info| in_macro_ext(cx, info))
}
/// check if a DefId's path matches the given absolute type path