Skip to content

Commit

Permalink
Add macro suggestions for macros imported with use
Browse files Browse the repository at this point in the history
This commit searchs modules for macro suggestions.
It also removes imported macro_rules from macro_names,
and adds more corner case checks for which macros
should be suggested in specific contexts.
  • Loading branch information
keeperofdakeys committed Feb 23, 2017
1 parent 4ecdc68 commit da6dc53
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 28 deletions.
1 change: 0 additions & 1 deletion src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,6 @@ impl<'a> Resolver<'a> {
binding: &'a NameBinding<'a>,
span: Span,
allow_shadowing: bool) {
self.macro_names.insert(name);
if self.builtin_macros.insert(name, binding).is_some() && !allow_shadowing {
let msg = format!("`{}` is already in scope", name);
let note =
Expand Down
7 changes: 4 additions & 3 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1264,7 +1264,7 @@ impl<'a> Resolver<'a> {
ribs: PerNS {
value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
macro_ns: None,
macro_ns: Some(vec![Rib::new(ModuleRibKind(graph_root))]),
},
label_ribs: Vec::new(),

Expand Down Expand Up @@ -2326,8 +2326,9 @@ impl<'a> Resolver<'a> {
};
}
}
if primary_ns != MacroNS && path.len() == 1 &&
self.macro_names.contains(&path[0].name) {
let is_builtin = self.builtin_macros.get(&path[0].name).cloned()
.map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
if primary_ns != MacroNS && (is_builtin || self.macro_names.contains(&path[0].name)) {
// Return some dummy definition, it's enough for error reporting.
return Some(
PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))
Expand Down
55 changes: 34 additions & 21 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use syntax::ast::{self, Name, Ident};
use syntax::attr;
use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension};
use syntax::ext::base::{Resolver as SyntaxResolver, SyntaxExtension};
use syntax::ext::base::MacroKind;
use syntax::ext::expand::{Expansion, mark_tts};
use syntax::ext::hygiene::Mark;
Expand Down Expand Up @@ -152,9 +152,6 @@ impl<'a> base::Resolver for Resolver<'a> {
}

fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
if let NormalTT(..) = *ext {
self.macro_names.insert(ident.name);
}
let def_id = DefId {
krate: BUILTIN_MACROS_CRATE,
index: DefIndex::new(self.macro_map.len()),
Expand Down Expand Up @@ -466,24 +463,40 @@ impl<'a> Resolver<'a> {

fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
err: &mut DiagnosticBuilder<'a>) {
let suggestion = match kind {
MacroKind::Bang =>
find_best_match_for_name(self.macro_names.iter(), name, None),
MacroKind::Attr |
MacroKind::Derive => {
// Find a suggestion from the legacy namespace.
// FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
let builtin_macros = self.builtin_macros.clone();
let names = builtin_macros.iter().filter_map(|(name, binding)| {
if binding.get_macro(self).kind() == kind {
Some(name)
} else {
None
}
});
find_best_match_for_name(names, name, None)
// First check if this is a locally-defined bang macro.
let suggestion = if let MacroKind::Bang = kind {
find_best_match_for_name(self.macro_names.iter(), name, None)
} else {
None
// Then check builtin macros.
}.or_else(|| {
// FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
let builtin_macros = self.builtin_macros.clone();
let names = builtin_macros.iter().filter_map(|(name, binding)| {
if binding.get_macro(self).kind() == kind {
Some(name)
} else {
None
}
});
find_best_match_for_name(names, name, None)
// Then check modules.
}).or_else(|| {
if !self.use_extern_macros {
return None;
}
};
let is_macro = |def| {
if let Def::Macro(_, def_kind) = def {
def_kind == kind
} else {
false
}
};
let ident = Ident::from_str(name);
self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
.as_ref().map(|s| Symbol::intern(s))
});

if let Some(suggestion) = suggestion {
if suggestion != name {
if let MacroKind::Bang = kind {
Expand Down
29 changes: 26 additions & 3 deletions src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,24 @@ extern crate attr_proc_macro;

use attr_proc_macro::attr_proc_macro;

#[derive(FooWithLongNam)]
//~^ ERROR cannot find derive macro `FooWithLongNam` in this scope
macro_rules! FooWithLongNam {
() => {}
}

#[derive(FooWithLongNan)]
//~^ ERROR cannot find derive macro `FooWithLongNan` in this scope
//~^^ HELP did you mean `FooWithLongName`?
struct Foo;

#[attr_proc_macra]
//~^ ERROR cannot find attribute macro `attr_proc_macra` in this scope
//~^^ HELP did you mean `attr_proc_macro`?
struct Bar;

#[FooWithLongNan]
//~^ ERROR cannot find attribute macro `FooWithLongNan` in this scope
struct Asdf;

#[derive(Dlone)]
//~^ ERROR cannot find derive macro `Dlone` in this scope
//~^^ HELP did you mean `Clone`?
Expand All @@ -41,4 +50,18 @@ struct A;
//~^^ HELP did you mean `Clona`?
struct B;

fn main() {}
#[derive(attr_proc_macra)]
//~^ ERROR cannot find derive macro `attr_proc_macra` in this scope
struct C;

fn main() {
FooWithLongNama!();
//~^ ERROR cannot find macro `FooWithLongNama!` in this scope
//~^^ HELP did you mean `FooWithLongNam!`?

attr_proc_macra!();
//~^ ERROR cannot find macro `attr_proc_macra!` in this scope

Dlona!();
//~^ ERROR cannot find macro `Dlona!` in this scope
}

0 comments on commit da6dc53

Please sign in to comment.