use rustc::hir;
use rustc::hir::def::Def as HirDef;
use rustc::hir::map::{Node, NodeItem};
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{LOCAL_CRATE, DefId};
use rustc::session::config::CrateType::CrateTypeExecutable;
use rustc::ty::{self, TyCtxt};
use rustc_typeck::hir_ty_to_ty;
attributes: lower_attributes(item.attrs.clone(), self),
}))
}
+ // FIXME(plietar): needs a new DefKind in rls-data
+ ast::ForeignItemKind::Ty => None,
}
}
self.tables.qpath_def(qpath, hir_id)
}
- Node::NodeBinding(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => {
- HirDef::Local(def_id)
- }
+ Node::NodeBinding(&hir::Pat {
+ node: hir::PatKind::Binding(_, canonical_id, ..), ..
+ }) => HirDef::Local(canonical_id),
Node::NodeTy(ty) => {
if let hir::Ty { node: hir::TyPath(ref qpath), .. } = *ty {
}
pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
+ // Returns true if the path is function type sugar, e.g., `Fn(A) -> B`.
+ fn fn_type(path: &ast::Path) -> bool {
+ if path.segments.len() != 1 {
+ return false;
+ }
+ if let Some(ref params) = path.segments[0].parameters {
+ if let ast::PathParameters::Parenthesized(_) = **params {
+ return true;
+ }
+ }
+ false
+ }
+
let def = self.get_path_def(id);
let sub_span = self.span_utils.span_for_last_ident(path.span);
filter!(self.span_utils, sub_span, path.span, None);
match def {
- HirDef::Upvar(..) |
- HirDef::Local(..) |
+ HirDef::Upvar(id, ..) |
+ HirDef::Local(id) => {
+ let span = self.span_from_span(sub_span.unwrap());
+ Some(Ref {
+ kind: RefKind::Variable,
+ span,
+ ref_id: id_from_node_id(id, self),
+ })
+ }
HirDef::Static(..) |
HirDef::Const(..) |
HirDef::AssociatedConst(..) |
ref_id: id_from_def_id(def.def_id()),
})
}
+ HirDef::Trait(def_id) if fn_type(path) => {
+ // Function type bounds are desugared in the parser, so we have to
+ // special case them here.
+ let fn_span = self.span_utils.span_for_first_ident(path.span);
+ fn_span.map(|span| Ref {
+ kind: RefKind::Type,
+ span: self.span_from_span(span),
+ ref_id: id_from_def_id(def_id),
+ })
+ }
HirDef::Struct(def_id) |
HirDef::Variant(def_id, ..) |
HirDef::Union(def_id) |
HirDef::Enum(def_id) |
HirDef::TyAlias(def_id) |
+ HirDef::TyForeign(def_id) |
HirDef::AssociatedTy(def_id) |
HirDef::Trait(def_id) |
HirDef::TyParam(def_id) => {
sig
}
-// An AST visitor for collecting paths from patterns.
-struct PathCollector {
- // The Row field identifies the kind of pattern.
- collected_paths: Vec<(NodeId, ast::Path, ast::Mutability)>,
+// An AST visitor for collecting paths (e.g., the names of structs) and formal
+// variables (idents) from patterns.
+struct PathCollector<'l> {
+ collected_paths: Vec<(NodeId, &'l ast::Path)>,
+ collected_idents: Vec<(NodeId, ast::Ident, Span, ast::Mutability)>,
}
-impl PathCollector {
- fn new() -> PathCollector {
- PathCollector { collected_paths: vec![] }
+impl<'l> PathCollector<'l> {
+ fn new() -> PathCollector<'l> {
+ PathCollector {
+ collected_paths: vec![],
+ collected_idents: vec![],
+ }
}
}
-impl<'a> Visitor<'a> for PathCollector {
- fn visit_pat(&mut self, p: &ast::Pat) {
+impl<'l, 'a: 'l> Visitor<'a> for PathCollector<'l> {
+ fn visit_pat(&mut self, p: &'a ast::Pat) {
match p.node {
PatKind::Struct(ref path, ..) => {
- self.collected_paths.push((p.id, path.clone(),
- ast::Mutability::Mutable));
+ self.collected_paths.push((p.id, path));
}
PatKind::TupleStruct(ref path, ..) |
PatKind::Path(_, ref path) => {
- self.collected_paths.push((p.id, path.clone(),
- ast::Mutability::Mutable));
+ self.collected_paths.push((p.id, path));
}
PatKind::Ident(bm, ref path1, _) => {
debug!("PathCollector, visit ident in pat {}: {:?} {:?}",
ast::BindingMode::ByRef(_) => ast::Mutability::Immutable,
ast::BindingMode::ByValue(mt) => mt,
};
- // collect path for either visit_local or visit_arm
- let path = ast::Path::from_ident(path1.span, path1.node);
- self.collected_paths.push((p.id, path, immut));
+ self.collected_idents.push((p.id, path1.node, path1.span, immut));
}
_ => {}
}
fn id_from_node_id(id: NodeId, scx: &SaveContext) -> rls_data::Id {
let def_id = scx.tcx.hir.opt_local_def_id(id);
- def_id.map(|id| id_from_def_id(id)).unwrap_or_else(null_id)
+ def_id.map(|id| id_from_def_id(id)).unwrap_or_else(|| {
+ // Create a *fake* `DefId` out of a `NodeId` by subtracting the `NodeId`
+ // out of the maximum u32 value. This will work unless you have *billions*
+ // of definitions in a single crate (very unlikely to actually happen).
+ rls_data::Id {
+ krate: LOCAL_CRATE.as_u32(),
+ index: !id.as_u32(),
+ }
+ })
}
fn null_id() -> rls_data::Id {