self.find_entry(id).and_then(|x| x.parent_node()).unwrap_or(id)
}
+ /// Returns the nearest enclosing scope. A scope is an item or block.
+ /// FIXME it is not clear to me that all items qualify as scopes - statics
+ /// and associated types probably shouldn't, for example. Behaviour in this
+ /// regard should be expected to be highly unstable.
+ pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> {
+ let mut last_id = id;
+ // Walk up the chain of parents until we find a 'scope'.
+ loop {
+ let cur_id = self.get_parent_node(last_id);
+ if cur_id == last_id {
+ return None;
+ }
+
+ match self.get(cur_id) {
+ NodeItem(_) |
+ NodeForeignItem(_) |
+ NodeTraitItem(_) |
+ NodeImplItem(_) |
+ NodeBlock(_) => {
+ return Some(cur_id);
+ }
+ _ => {}
+ }
+
+ last_id = cur_id;
+ }
+ }
+
pub fn get_parent_did(&self, id: NodeId) -> DefId {
let parent = self.get_parent(id);
match self.find_entry(parent) {
qualname: qualname,
declaration: None,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap(),
})
}
ast::ItemStatic(ref typ, mt, ref expr) => {
name: get_ident(item.ident).to_string(),
qualname: qualname,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap(),
value: value,
type_value: ty_to_string(&typ),
})
name: get_ident(item.ident).to_string(),
qualname: qualname,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap(),
value: self.span_utils.snippet(expr.span),
type_value: ty_to_string(&typ),
})
name: get_ident(item.ident).to_string(),
qualname: qualname,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap(),
filename: filename,
})
},
value: val,
span: sub_span.unwrap(),
qualname: enum_name,
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap(),
})
},
ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => {
let mut type_data = None;
let sub_span;
- let parent = self.tcx.map.get_parent(item.id);
+ let parent = self.tcx.map.get_enclosing_scope(item.id).unwrap();
match typ.node {
// Common case impl for a struct or something basic.
return Some(Data::VariableRefData(VariableRefData {
name: get_ident(ident.node).to_string(),
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(expr.id),
+ scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap(),
ref_id: f.id,
}));
}
let sub_span = self.span_utils.span_for_last_ident(path.span);
Some(Data::TypeRefData(TypeRefData {
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(expr.id),
+ scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap(),
ref_id: def_id,
}))
}