Auto merge of #36487 - nrc:save-doc-urls, r=@eddyb

save-analysis: better 'parent' info

In particular, this fixes some bugs displaying doc URLs for method calls.
This commit is contained in:
bors 2016-09-18 14:00:02 -07:00 committed by GitHub
commit 55bf6a4f87
4 changed files with 69 additions and 43 deletions

View File

@ -167,7 +167,7 @@ pub struct FunctionData {
pub scope: NodeId,
pub value: String,
pub visibility: Visibility,
pub parent: Option<NodeId>,
pub parent: Option<DefId>,
pub docs: String,
}
@ -250,6 +250,7 @@ pub struct MethodData {
pub scope: NodeId,
pub value: String,
pub decl_id: Option<DefId>,
pub parent: Option<DefId>,
pub visibility: Visibility,
pub docs: String,
}
@ -300,7 +301,7 @@ pub struct StructVariantData {
pub type_value: String,
pub value: String,
pub scope: NodeId,
pub parent: Option<NodeId>,
pub parent: Option<DefId>,
pub docs: String,
}
@ -326,7 +327,7 @@ pub struct TupleVariantData {
pub type_value: String,
pub value: String,
pub scope: NodeId,
pub parent: Option<NodeId>,
pub parent: Option<DefId>,
pub docs: String,
}
@ -339,7 +340,7 @@ pub struct TypeDefData {
pub qualname: String,
pub value: String,
pub visibility: Visibility,
pub parent: Option<NodeId>,
pub parent: Option<DefId>,
pub docs: String,
}
@ -380,7 +381,7 @@ pub struct VariableData {
pub qualname: String,
pub span: Span,
pub scope: NodeId,
pub parent: Option<NodeId>,
pub parent: Option<DefId>,
pub value: String,
pub type_value: String,
pub visibility: Visibility,

View File

@ -27,9 +27,10 @@
//! is used for recording the output in a format-agnostic way (see CsvDumper
//! for an example).
use rustc::hir;
use rustc::hir::def::Def;
use rustc::hir::def_id::DefId;
use rustc::hir::map::Node;
use rustc::hir::map::{Node, NodeItem};
use rustc::session::Session;
use rustc::ty::{self, TyCtxt, ImplOrTraitItem, ImplOrTraitItemContainer};
@ -47,7 +48,7 @@
use super::{escape, generated_code, SaveContext, PathCollector, docs_for_attrs};
use super::data::*;
use super::dump::Dump;
use super::external_data::Lower;
use super::external_data::{Lower, make_def_id};
use super::span_utils::SpanUtils;
use super::recorder;
@ -271,11 +272,13 @@ fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) {
// looks up anything, not just a type
fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
match self.tcx.expect_def(ref_id) {
Def::PrimTy(..) => None,
Def::SelfTy(..) => None,
def => Some(def.def_id()),
}
self.tcx.expect_def_or_none(ref_id).and_then(|def| {
match def {
Def::PrimTy(..) => None,
Def::SelfTy(..) => None,
def => Some(def.def_id()),
}
})
}
fn process_def_kind(&mut self,
@ -399,20 +402,36 @@ fn process_method(&mut self,
if !self.span.filter_generated(Some(method_data.span), span) {
let container =
self.tcx.impl_or_trait_item(self.tcx.map.local_def_id(id)).container();
let decl_id = if let ImplOrTraitItemContainer::ImplContainer(id) = container {
self.tcx.trait_id_of_impl(id).and_then(|id| {
for item in &**self.tcx.trait_items(id) {
if let &ImplOrTraitItem::MethodTraitItem(ref m) = item {
if m.name == name {
return Some(m.def_id);
let mut trait_id;
let mut decl_id = None;
match container {
ImplOrTraitItemContainer::ImplContainer(id) => {
trait_id = self.tcx.trait_id_of_impl(id);
match trait_id {
Some(id) => {
for item in &**self.tcx.trait_items(id) {
if let &ImplOrTraitItem::MethodTraitItem(ref m) = item {
if m.name == name {
decl_id = Some(m.def_id);
break;
}
}
}
}
None => {
if let Some(NodeItem(item)) = self.tcx.map.get_if_local(id) {
if let hir::ItemImpl(_, _, _, _, ref ty, _) = item.node {
trait_id = self.lookup_type_ref(ty.id);
}
}
}
}
None
})
} else {
None
};
}
ImplOrTraitItemContainer::TraitContainer(id) => {
trait_id = Some(id);
}
}
self.dumper.method(MethodData {
id: method_data.id,
@ -422,6 +441,7 @@ fn process_method(&mut self,
qualname: method_data.qualname.clone(),
value: sig_str,
decl_id: decl_id,
parent: trait_id,
visibility: vis,
docs: docs_for_attrs(attrs),
}.lower(self.tcx));
@ -544,7 +564,7 @@ fn process_assoc_const(&mut self,
span: Span,
typ: &ast::Ty,
expr: &ast::Expr,
parent_id: NodeId,
parent_id: DefId,
vis: Visibility,
attrs: &[Attribute]) {
let qualname = format!("::{}", self.tcx.node_path_str(id));
@ -659,7 +679,7 @@ fn process_enum(&mut self,
type_value: enum_data.qualname.clone(),
value: val,
scope: enum_data.scope,
parent: Some(item.id),
parent: Some(make_def_id(item.id, &self.tcx.map)),
docs: docs_for_attrs(&variant.node.attrs),
}.lower(self.tcx));
}
@ -684,7 +704,7 @@ fn process_enum(&mut self,
type_value: enum_data.qualname.clone(),
value: val,
scope: enum_data.scope,
parent: Some(item.id),
parent: Some(make_def_id(item.id, &self.tcx.map)),
docs: docs_for_attrs(&variant.node.attrs),
}.lower(self.tcx));
}
@ -738,7 +758,8 @@ fn process_impl(&mut self,
}
self.process_generic_params(type_parameters, item.span, "", item.id);
for impl_item in impl_items {
self.process_impl_item(impl_item, item.id);
let map = &self.tcx.map;
self.process_impl_item(impl_item, make_def_id(item.id, map));
}
}
@ -809,7 +830,8 @@ fn process_trait(&mut self,
// walk generics and methods
self.process_generic_params(generics, item.span, &qualname, item.id);
for method in methods {
self.process_trait_item(method, item.id)
let map = &self.tcx.map;
self.process_trait_item(method, make_def_id(item.id, map))
}
}
@ -1076,7 +1098,7 @@ fn process_macro_use(&mut self, span: Span, id: NodeId) {
}
}
fn process_trait_item(&mut self, trait_item: &ast::TraitItem, trait_id: NodeId) {
fn process_trait_item(&mut self, trait_item: &ast::TraitItem, trait_id: DefId) {
self.process_macro_use(trait_item.span, trait_item.id);
match trait_item.node {
ast::TraitItemKind::Const(ref ty, Some(ref expr)) => {
@ -1104,7 +1126,7 @@ fn process_trait_item(&mut self, trait_item: &ast::TraitItem, trait_id: NodeId)
}
}
fn process_impl_item(&mut self, impl_item: &ast::ImplItem, impl_id: NodeId) {
fn process_impl_item(&mut self, impl_item: &ast::ImplItem, impl_id: DefId) {
self.process_macro_use(impl_item.span, impl_item.id);
match impl_item.node {
ast::ImplItemKind::Const(ref ty, ref expr) => {

View File

@ -23,7 +23,7 @@ pub trait Lower {
fn lower(self, tcx: TyCtxt) -> Self::Target;
}
fn make_def_id(id: NodeId, map: &Map) -> DefId {
pub fn make_def_id(id: NodeId, map: &Map) -> DefId {
map.opt_local_def_id(id).unwrap_or(null_def_id())
}
@ -188,7 +188,7 @@ fn lower(self, tcx: TyCtxt) -> FunctionData {
scope: make_def_id(self.scope, &tcx.map),
value: self.value,
visibility: self.visibility,
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
parent: self.parent,
docs: self.docs,
}
}
@ -353,7 +353,7 @@ fn lower(self, tcx: TyCtxt) -> MethodData {
value: self.value,
decl_id: self.decl_id,
visibility: self.visibility,
parent: Some(make_def_id(self.scope, &tcx.map)),
parent: self.parent,
docs: self.docs,
}
}
@ -471,7 +471,7 @@ fn lower(self, tcx: TyCtxt) -> StructVariantData {
type_value: self.type_value,
value: self.value,
scope: make_def_id(self.scope, &tcx.map),
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
parent: self.parent,
docs: self.docs,
}
}
@ -533,7 +533,7 @@ fn lower(self, tcx: TyCtxt) -> TupleVariantData {
type_value: self.type_value,
value: self.value,
scope: make_def_id(self.scope, &tcx.map),
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
parent: self.parent,
docs: self.docs,
}
}
@ -563,7 +563,7 @@ fn lower(self, tcx: TyCtxt) -> TypeDefData {
qualname: self.qualname,
value: self.value,
visibility: self.visibility,
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
parent: self.parent,
docs: self.docs,
}
}
@ -668,7 +668,7 @@ fn lower(self, tcx: TyCtxt) -> VariableData {
scope: make_def_id(self.scope, &tcx.map),
value: self.value,
type_value: self.type_value,
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
parent: self.parent,
visibility: self.visibility,
docs: self.docs,
}

View File

@ -64,6 +64,7 @@
pub use self::json_api_dumper::JsonApiDumper;
pub use self::json_dumper::JsonDumper;
pub use self::data::*;
pub use self::external_data::make_def_id;
pub use self::dump::Dump;
pub use self::dump_visitor::DumpVisitor;
use self::span_utils::SpanUtils;
@ -295,7 +296,7 @@ pub fn get_field_data(&self, field: &ast::StructField,
qualname: qualname,
span: sub_span.unwrap(),
scope: scope,
parent: Some(scope),
parent: Some(make_def_id(scope, &self.tcx.map)),
value: "".to_owned(),
type_value: typ,
visibility: From::from(&field.vis),
@ -312,7 +313,8 @@ pub fn get_method_data(&self, id: ast::NodeId,
name: ast::Name, span: Span) -> Option<FunctionData> {
// The qualname for a method is the trait name or name of the struct in an impl in
// which the method is declared in, followed by the method's name.
let (qualname, vis, docs) = match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) {
let (qualname, parent_scope, vis, docs) =
match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) {
Some(impl_id) => match self.tcx.map.get_if_local(impl_id) {
Some(NodeItem(item)) => {
match item.node {
@ -320,12 +322,13 @@ pub fn get_method_data(&self, id: ast::NodeId,
let mut result = String::from("<");
result.push_str(&rustc::hir::print::ty_to_string(&ty));
if let Some(def_id) = self.tcx.trait_id_of_impl(impl_id) {
let trait_id = self.tcx.trait_id_of_impl(impl_id);
if let Some(def_id) = trait_id {
result.push_str(" as ");
result.push_str(&self.tcx.item_path_str(def_id));
}
result.push_str(">");
(result, From::from(&item.vis), docs_for_attrs(&item.attrs))
(result, trait_id, From::from(&item.vis), docs_for_attrs(&item.attrs))
}
_ => {
span_bug!(span,
@ -348,6 +351,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
match self.tcx.map.get_if_local(def_id) {
Some(NodeItem(item)) => {
(format!("::{}", self.tcx.item_path_str(def_id)),
Some(def_id),
From::from(&item.vis),
docs_for_attrs(&item.attrs))
}
@ -381,7 +385,6 @@ pub fn get_method_data(&self, id: ast::NodeId,
let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn);
filter!(self.span_utils, sub_span, span, None);
let parent_scope = self.enclosing_scope(id);
Some(FunctionData {
id: id,
name: name.to_string(),
@ -392,7 +395,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
// FIXME you get better data here by using the visitor.
value: String::new(),
visibility: vis,
parent: Some(parent_scope),
parent: parent_scope,
docs: docs,
})
}