|
10 | 10 |
|
11 | 11 | use front::map::DefPathData;
|
12 | 12 | use middle::cstore::LOCAL_CRATE;
|
13 |
| -use middle::def_id::DefId; |
| 13 | +use middle::def_id::{DefId, CRATE_DEF_INDEX}; |
14 | 14 | use ty::{self, Ty, TyCtxt};
|
15 | 15 | use syntax::ast;
|
16 | 16 |
|
@@ -75,9 +75,51 @@ impl<'tcx> TyCtxt<'tcx> {
|
75 | 75 | }
|
76 | 76 | }
|
77 | 77 |
|
| 78 | + /// If possible, this pushes a global path resolving to `external_def_id` that is visible |
| 79 | + /// from at least one local module and returns true. If the crate defining `external_def_id` is |
| 80 | + /// declared with an `extern crate`, the path is guarenteed to use the `extern crate`. |
| 81 | + pub fn try_push_visible_item_path<T>(&self, buffer: &mut T, external_def_id: DefId) -> bool |
| 82 | + where T: ItemPathBuffer |
| 83 | + { |
| 84 | + let visible_parent_map = self.sess.cstore.visible_parent_map(); |
| 85 | + |
| 86 | + let (mut cur_def, mut cur_path) = (external_def_id, Vec::<ast::Name>::new()); |
| 87 | + loop { |
| 88 | + // If `cur_def` is a direct or injected extern crate, push the path to the crate |
| 89 | + // followed by the path to the item within the crate and return. |
| 90 | + if cur_def.index == CRATE_DEF_INDEX { |
| 91 | + match self.sess.cstore.extern_crate(cur_def.krate) { |
| 92 | + Some(extern_crate) if extern_crate.direct => { |
| 93 | + self.push_item_path(buffer, extern_crate.def_id); |
| 94 | + cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count(); |
| 95 | + return true; |
| 96 | + } |
| 97 | + None => { |
| 98 | + buffer.push(&self.crate_name(cur_def.krate)); |
| 99 | + cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count(); |
| 100 | + return true; |
| 101 | + } |
| 102 | + _ => {}, |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + cur_path.push(self.sess.cstore.item_name(cur_def)); |
| 107 | + match visible_parent_map.get(&cur_def) { |
| 108 | + Some(&def) => cur_def = def, |
| 109 | + None => return false, |
| 110 | + }; |
| 111 | + } |
| 112 | + } |
| 113 | + |
78 | 114 | pub fn push_item_path<T>(&self, buffer: &mut T, def_id: DefId)
|
79 | 115 | where T: ItemPathBuffer
|
80 | 116 | {
|
| 117 | + match *buffer.root_mode() { |
| 118 | + RootMode::Local if !def_id.is_local() => |
| 119 | + if self.try_push_visible_item_path(buffer, def_id) { return }, |
| 120 | + _ => {} |
| 121 | + } |
| 122 | + |
81 | 123 | let key = self.def_key(def_id);
|
82 | 124 | match key.disambiguated_data.data {
|
83 | 125 | DefPathData::CrateRoot => {
|
|
0 commit comments