use session::search_paths::PathKind;
use util::nodemap::{NodeMap, FnvHashMap};
-use syntax::ast::{NodeId, NodeIdAssigner};
+use syntax::ast::{NodeId, NodeIdAssigner, Name};
use syntax::codemap::Span;
use syntax::diagnostic::{self, Emitter};
use syntax::diagnostics;
use std::path::{Path, PathBuf};
use std::cell::{Cell, RefCell};
+use std::collections::HashSet;
use std::env;
pub mod config;
/// didn't already find one, and this tracks what was injected.
pub injected_allocator: Cell<Option<ast::CrateNum>>,
+ /// Names of all bang-style macros and syntax extensions
+ /// available in this crate
+ pub available_macros: RefCell<HashSet<Name>>,
+
next_node_id: Cell<ast::NodeId>,
}
can_print_warnings: can_print_warnings,
next_node_id: Cell::new(1),
injected_allocator: Cell::new(None),
+ available_macros: RefCell::new(HashSet::new()),
};
sess
recursion_limit: sess.recursion_limit.get(),
trace_mac: sess.opts.debugging_opts.trace_macros,
};
- let ret = syntax::ext::expand::expand_crate(&sess.parse_sess,
- cfg,
- macros,
- syntax_exts,
- &mut feature_gated_cfgs,
- krate);
+ let (ret, macro_names) = syntax::ext::expand::expand_crate(&sess.parse_sess,
+ cfg,
+ macros,
+ syntax_exts,
+ &mut feature_gated_cfgs,
+ krate);
if cfg!(windows) {
env::set_var("PATH", &_old_path);
}
+ *sess.available_macros.borrow_mut() = macro_names;
ret
});
)
}
+enum SuggestionType {
+ Macro(String),
+ Function(String),
+ NotFound,
+}
+
pub enum ResolutionError<'a> {
/// error E0401: can't use type parameters from outer function
TypeParametersFromOuterFunction,
NoSuggestion
}
- fn find_best_match_for_name(&mut self, name: &str) -> Option<String> {
+ fn find_best_match_for_name(&mut self, name: &str) -> SuggestionType {
let mut maybes: Vec<token::InternedString> = Vec::new();
let mut values: Vec<usize> = Vec::new();
+ if let Some(macro_name) = self.session.available_macros
+ .borrow().iter().find(|n| n.as_str() == name) {
+ return SuggestionType::Macro(format!("{}!", macro_name));
+ }
+
for rib in self.value_ribs.iter().rev() {
for (&k, _) in &rib.bindings {
maybes.push(k.as_str());
if !values.is_empty() && values[smallest] <= max_distance && name != &maybes[smallest][..] {
- Some(maybes[smallest].to_string())
+ SuggestionType::Function(maybes[smallest].to_string())
} else {
- None
+ SuggestionType::NotFound
}
}
NoSuggestion => {
// limit search to 5 to reduce the number
// of stupid suggestions
- self.find_best_match_for_name(&path_name)
- .map_or("".to_string(), |x| format!("`{}`", x))
+ match self.find_best_match_for_name(&path_name) {
+ SuggestionType::Macro(s) => {
+ format!("the macro `{}`", s)
+ }
+ SuggestionType::Function(s) => format!("`{}`", s),
+ SuggestionType::NotFound => "".to_string(),
+ }
}
Field => format!("`self.{}`", path_name),
Method |
use ext::mtwt;
use fold::Folder;
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use std::default::Default;
///
/// This environment maps Names to SyntaxExtensions.
pub struct SyntaxEnv {
- chain: Vec<MapChainFrame> ,
+ chain: Vec<MapChainFrame>,
+ /// All bang-style macro/extension names
+ /// encountered so far; to be used for diagnostics in resolve
+ pub names: HashSet<Name>,
}
// impl question: how to implement it? Initially, the
impl SyntaxEnv {
fn new() -> SyntaxEnv {
- let mut map = SyntaxEnv { chain: Vec::new() };
+ let mut map = SyntaxEnv { chain: Vec::new() , names: HashSet::new()};
map.push_frame();
map
}
}
pub fn insert(&mut self, k: Name, v: SyntaxExtension) {
+ if let NormalTT(..) = v {
+ self.names.insert(k);
+ }
self.find_escape_frame().map.insert(k, Rc::new(v));
}
// except according to those terms.
use ast::{Block, Crate, DeclLocal, ExprMac, PatMac};
-use ast::{Local, Ident, Mac_};
+use ast::{Local, Ident, Mac_, Name};
use ast::{ItemMac, MacStmtWithSemicolon, Mrk, Stmt, StmtDecl, StmtMac};
use ast::{StmtExpr, StmtSemi};
use ast::TokenTree;
use visit::Visitor;
use std_inject;
+use std::collections::HashSet;
+
pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
let expr_span = e.span;
imported_macros: Vec<ast::MacroDef>,
user_exts: Vec<NamedSyntaxExtension>,
feature_gated_cfgs: &mut Vec<GatedCfg>,
- c: Crate) -> Crate {
+ c: Crate) -> (Crate, HashSet<Name>) {
let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg,
feature_gated_cfgs);
if std_inject::no_core(&c) {
} else {
cx.crate_root = Some("std");
}
+ let ret = {
+ let mut expander = MacroExpander::new(&mut cx);
- let mut expander = MacroExpander::new(&mut cx);
-
- for def in imported_macros {
- expander.cx.insert_macro(def);
- }
+ for def in imported_macros {
+ expander.cx.insert_macro(def);
+ }
- for (name, extension) in user_exts {
- expander.cx.syntax_env.insert(name, extension);
- }
+ for (name, extension) in user_exts {
+ expander.cx.syntax_env.insert(name, extension);
+ }
- let mut ret = expander.fold_crate(c);
- ret.exported_macros = expander.cx.exported_macros.clone();
- parse_sess.span_diagnostic.handler().abort_if_errors();
- return ret;
+ let mut ret = expander.fold_crate(c);
+ ret.exported_macros = expander.cx.exported_macros.clone();
+ parse_sess.span_diagnostic.handler().abort_if_errors();
+ ret
+ };
+ return (ret, cx.syntax_env.names);
}
// HYGIENIC CONTEXT EXTENSION:
let ps = parse::ParseSess::new();
let crate_ast = panictry!(string_to_parser(&ps, crate_str).parse_crate_mod());
// the cfg argument actually does matter, here...
- expand_crate(&ps,test_ecfg(),vec!(),vec!(), &mut vec![], crate_ast)
+ expand_crate(&ps,test_ecfg(),vec!(),vec!(), &mut vec![], crate_ast).0
}
// find the pat_ident paths in a crate
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
+
+fn main() {
+ assert(true); //~ERROR unresolved name `assert`. Did you mean the macro `assert!`?
+}