aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-10-30 15:41:50 +0000
committerAleksey Kladov <[email protected]>2019-10-30 15:41:50 +0000
commit0bc7d285189caaffc13e4d6856baf895f72ed80c (patch)
tree792693f3b35d2a23107ee5a1e4bbb13bc2806c41
parente34e71c62d9b4cf0ab237969e03ecde893ab347b (diff)
refactor $crate handling
Introduce proper hygiene module, which should grow quite a bit eventually.
-rw-r--r--crates/ra_hir/src/expr/lower.rs4
-rw-r--r--crates/ra_hir/src/impl_block.rs12
-rw-r--r--crates/ra_hir_def/src/attr.rs18
-rw-r--r--crates/ra_hir_def/src/hygiene.rs40
-rw-r--r--crates/ra_hir_def/src/lib.rs1
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs31
-rw-r--r--crates/ra_hir_def/src/path.rs101
7 files changed, 118 insertions, 89 deletions
diff --git a/crates/ra_hir/src/expr/lower.rs b/crates/ra_hir/src/expr/lower.rs
index ad029b868..575d78198 100644
--- a/crates/ra_hir/src/expr/lower.rs
+++ b/crates/ra_hir/src/expr/lower.rs
@@ -1,6 +1,7 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{ 3use hir_def::{
4 hygiene::Hygiene,
4 name::{self, AsName, Name}, 5 name::{self, AsName, Name},
5 path::GenericArgs, 6 path::GenericArgs,
6 type_ref::TypeRef, 7 type_ref::TypeRef,
@@ -597,7 +598,8 @@ where
597 } 598 }
598 599
599 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 600 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
600 Path::from_src(Source { ast: path, file_id: self.current_file_id }, self.db) 601 let hygiene = Hygiene::new(self.db, self.current_file_id);
602 Path::from_src(path, &hygiene)
601 } 603 }
602} 604}
603 605
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 518330713..9e4a40017 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -3,7 +3,7 @@
3use rustc_hash::FxHashMap; 3use rustc_hash::FxHashMap;
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use hir_def::{attr::Attr, type_ref::TypeRef}; 6use hir_def::{attr::Attr, hygiene::Hygiene, type_ref::TypeRef};
7use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 7use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
8use ra_cfg::CfgOptions; 8use ra_cfg::CfgOptions;
9use ra_syntax::{ 9use ra_syntax::{
@@ -227,10 +227,11 @@ impl ModuleImplBlocks {
227 owner: &dyn ast::ModuleItemOwner, 227 owner: &dyn ast::ModuleItemOwner,
228 file_id: HirFileId, 228 file_id: HirFileId,
229 ) { 229 ) {
230 let hygiene = Hygiene::new(db, file_id);
230 for item in owner.items_with_macros() { 231 for item in owner.items_with_macros() {
231 match item { 232 match item {
232 ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => { 233 ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => {
233 let attrs = Attr::from_attrs_owner(file_id, &impl_block_ast, db); 234 let attrs = Attr::from_attrs_owner(&impl_block_ast, &hygiene);
234 if attrs.map_or(false, |attrs| { 235 if attrs.map_or(false, |attrs| {
235 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) 236 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
236 }) { 237 }) {
@@ -247,7 +248,7 @@ impl ModuleImplBlocks {
247 } 248 }
248 ast::ItemOrMacro::Item(_) => (), 249 ast::ItemOrMacro::Item(_) => (),
249 ast::ItemOrMacro::Macro(macro_call) => { 250 ast::ItemOrMacro::Macro(macro_call) => {
250 let attrs = Attr::from_attrs_owner(file_id, &macro_call, db); 251 let attrs = Attr::from_attrs_owner(&macro_call, &hygiene);
251 if attrs.map_or(false, |attrs| { 252 if attrs.map_or(false, |attrs| {
252 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) 253 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
253 }) { 254 }) {
@@ -256,9 +257,8 @@ impl ModuleImplBlocks {
256 257
257 //FIXME: we should really cut down on the boilerplate required to process a macro 258 //FIXME: we should really cut down on the boilerplate required to process a macro
258 let ast_id = AstId::new(file_id, db.ast_id_map(file_id).ast_id(&macro_call)); 259 let ast_id = AstId::new(file_id, db.ast_id_map(file_id).ast_id(&macro_call));
259 if let Some(path) = macro_call 260 if let Some(path) =
260 .path() 261 macro_call.path().and_then(|path| Path::from_src(path, &hygiene))
261 .and_then(|path| Path::from_src(Source { ast: path, file_id }, db))
262 { 262 {
263 if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path) 263 if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path)
264 { 264 {
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 248f03cdf..71f92adc2 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -2,7 +2,6 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_expand::db::AstDatabase;
6use mbe::ast_to_token_tree; 5use mbe::ast_to_token_tree;
7use ra_cfg::CfgOptions; 6use ra_cfg::CfgOptions;
8use ra_syntax::{ 7use ra_syntax::{
@@ -11,7 +10,7 @@ use ra_syntax::{
11}; 10};
12use tt::Subtree; 11use tt::Subtree;
13 12
14use crate::{path::Path, HirFileId, Source}; 13use crate::{hygiene::Hygiene, path::Path};
15 14
16#[derive(Debug, Clone, PartialEq, Eq)] 15#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct Attr { 16pub struct Attr {
@@ -26,11 +25,8 @@ pub enum AttrInput {
26} 25}
27 26
28impl Attr { 27impl Attr {
29 pub(crate) fn from_src( 28 pub(crate) fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> {
30 Source { file_id, ast }: Source<ast::Attr>, 29 let path = Path::from_src(ast.path()?, hygiene)?;
31 db: &impl AstDatabase,
32 ) -> Option<Attr> {
33 let path = Path::from_src(Source { file_id, ast: ast.path()? }, db)?;
34 let input = match ast.input() { 30 let input = match ast.input() {
35 None => None, 31 None => None,
36 Some(ast::AttrInput::Literal(lit)) => { 32 Some(ast::AttrInput::Literal(lit)) => {
@@ -46,17 +42,13 @@ impl Attr {
46 Some(Attr { path, input }) 42 Some(Attr { path, input })
47 } 43 }
48 44
49 pub fn from_attrs_owner( 45 pub fn from_attrs_owner(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Option<Arc<[Attr]>> {
50 file_id: HirFileId,
51 owner: &dyn AttrsOwner,
52 db: &impl AstDatabase,
53 ) -> Option<Arc<[Attr]>> {
54 let mut attrs = owner.attrs().peekable(); 46 let mut attrs = owner.attrs().peekable();
55 if attrs.peek().is_none() { 47 if attrs.peek().is_none() {
56 // Avoid heap allocation 48 // Avoid heap allocation
57 return None; 49 return None;
58 } 50 }
59 Some(attrs.flat_map(|ast| Attr::from_src(Source { file_id, ast }, db)).collect()) 51 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect())
60 } 52 }
61 53
62 pub fn is_simple_atom(&self, name: &str) -> bool { 54 pub fn is_simple_atom(&self, name: &str) -> bool {
diff --git a/crates/ra_hir_def/src/hygiene.rs b/crates/ra_hir_def/src/hygiene.rs
new file mode 100644
index 000000000..e1ae58a3b
--- /dev/null
+++ b/crates/ra_hir_def/src/hygiene.rs
@@ -0,0 +1,40 @@
1//! This modules handles hygiene information.
2//!
3//! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at
4//! this moment, this is horribly incomplete and handles only `$crate`.
5// Should this be moved to `hir_expand`? Seems like it.
6
7use hir_expand::{db::AstDatabase, HirFileId};
8use ra_db::CrateId;
9use ra_syntax::ast;
10
11use crate::{
12 either::Either,
13 name::{AsName, Name},
14};
15
16#[derive(Debug)]
17pub struct Hygiene {
18 // This is what `$crate` expands to
19 def_crate: Option<CrateId>,
20}
21
22impl Hygiene {
23 pub fn new(db: &impl AstDatabase, file_id: HirFileId) -> Hygiene {
24 Hygiene { def_crate: file_id.macro_crate(db) }
25 }
26
27 pub(crate) fn new_unhygienic() -> Hygiene {
28 Hygiene { def_crate: None }
29 }
30
31 // FIXME: this should just return name
32 pub(crate) fn name_ref_to_name(&self, name_ref: ast::NameRef) -> Either<Name, CrateId> {
33 if let Some(def_crate) = self.def_crate {
34 if name_ref.text() == "$crate" {
35 return Either::B(def_crate);
36 }
37 }
38 Either::A(name_ref.as_name())
39 }
40}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 95d503325..61ccdb30d 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -13,6 +13,7 @@ pub mod attr;
13pub mod name; 13pub mod name;
14pub mod path; 14pub mod path;
15pub mod type_ref; 15pub mod type_ref;
16pub mod hygiene;
16 17
17// FIXME: this should be private 18// FIXME: this should be private
18pub mod nameres; 19pub mod nameres;
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 86b4fef96..636364628 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -13,6 +13,7 @@ use crate::{
13 attr::Attr, 13 attr::Attr,
14 db::DefDatabase2, 14 db::DefDatabase2,
15 either::Either, 15 either::Either,
16 hygiene::Hygiene,
16 name::{AsName, Name}, 17 name::{AsName, Name},
17 path::Path, 18 path::Path,
18 FileAstId, HirFileId, ModuleSource, Source, 19 FileAstId, HirFileId, ModuleSource, Source,
@@ -78,7 +79,7 @@ impl RawItems {
78 source_ast_id_map: db.ast_id_map(file_id), 79 source_ast_id_map: db.ast_id_map(file_id),
79 source_map: ImportSourceMap::default(), 80 source_map: ImportSourceMap::default(),
80 file_id, 81 file_id,
81 db, 82 hygiene: Hygiene::new(db, file_id),
82 }; 83 };
83 if let Some(node) = db.parse_or_expand(file_id) { 84 if let Some(node) = db.parse_or_expand(file_id) {
84 if let Some(source_file) = ast::SourceFile::cast(node.clone()) { 85 if let Some(source_file) = ast::SourceFile::cast(node.clone()) {
@@ -204,15 +205,15 @@ pub struct MacroData {
204 pub export: bool, 205 pub export: bool,
205} 206}
206 207
207struct RawItemsCollector<DB> { 208struct RawItemsCollector {
208 raw_items: RawItems, 209 raw_items: RawItems,
209 source_ast_id_map: Arc<AstIdMap>, 210 source_ast_id_map: Arc<AstIdMap>,
210 source_map: ImportSourceMap, 211 source_map: ImportSourceMap,
211 file_id: HirFileId, 212 file_id: HirFileId,
212 db: DB, 213 hygiene: Hygiene,
213} 214}
214 215
215impl<DB: AstDatabase> RawItemsCollector<&DB> { 216impl RawItemsCollector {
216 fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) { 217 fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) {
217 for item_or_macro in body.items_with_macros() { 218 for item_or_macro in body.items_with_macros() {
218 match item_or_macro { 219 match item_or_macro {
@@ -309,9 +310,10 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
309 let is_prelude = use_item.has_atom_attr("prelude_import"); 310 let is_prelude = use_item.has_atom_attr("prelude_import");
310 let attrs = self.parse_attrs(&use_item); 311 let attrs = self.parse_attrs(&use_item);
311 312
313 let mut buf = Vec::new();
312 Path::expand_use_item( 314 Path::expand_use_item(
313 Source { ast: use_item, file_id: self.file_id }, 315 Source { ast: use_item, file_id: self.file_id },
314 self.db, 316 &self.hygiene,
315 |path, use_tree, is_glob, alias| { 317 |path, use_tree, is_glob, alias| {
316 let import_data = ImportData { 318 let import_data = ImportData {
317 path, 319 path,
@@ -321,14 +323,12 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
321 is_extern_crate: false, 323 is_extern_crate: false,
322 is_macro_use: false, 324 is_macro_use: false,
323 }; 325 };
324 self.push_import( 326 buf.push((import_data, Either::A(AstPtr::new(use_tree))));
325 current_module,
326 attrs.clone(),
327 import_data,
328 Either::A(AstPtr::new(use_tree)),
329 );
330 }, 327 },
331 ) 328 );
329 for (import_data, ptr) in buf {
330 self.push_import(current_module, attrs.clone(), import_data, ptr);
331 }
332 } 332 }
333 333
334 fn add_extern_crate_item( 334 fn add_extern_crate_item(
@@ -361,10 +361,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
361 361
362 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { 362 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) {
363 let attrs = self.parse_attrs(&m); 363 let attrs = self.parse_attrs(&m);
364 let path = match m 364 let path = match m.path().and_then(|path| Path::from_src(path, &self.hygiene)) {
365 .path()
366 .and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db))
367 {
368 Some(it) => it, 365 Some(it) => it,
369 _ => return, 366 _ => return,
370 }; 367 };
@@ -402,6 +399,6 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
402 } 399 }
403 400
404 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { 401 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
405 Attr::from_attrs_owner(self.file_id, item, self.db) 402 Attr::from_attrs_owner(item, &self.hygiene)
406 } 403 }
407} 404}
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index fe060437d..39f394c3f 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -2,7 +2,6 @@
2 2
3use std::{iter, sync::Arc}; 3use std::{iter, sync::Arc};
4 4
5use hir_expand::db::AstDatabase;
6use ra_db::CrateId; 5use ra_db::CrateId;
7use ra_syntax::{ 6use ra_syntax::{
8 ast::{self, NameOwner, TypeAscriptionOwner}, 7 ast::{self, NameOwner, TypeAscriptionOwner},
@@ -10,6 +9,8 @@ use ra_syntax::{
10}; 9};
11 10
12use crate::{ 11use crate::{
12 either::Either,
13 hygiene::Hygiene,
13 name::{self, AsName, Name}, 14 name::{self, AsName, Name},
14 type_ref::TypeRef, 15 type_ref::TypeRef,
15 Source, 16 Source,
@@ -68,11 +69,11 @@ impl Path {
68 /// Calls `cb` with all paths, represented by this use item. 69 /// Calls `cb` with all paths, represented by this use item.
69 pub fn expand_use_item( 70 pub fn expand_use_item(
70 item_src: Source<ast::UseItem>, 71 item_src: Source<ast::UseItem>,
71 db: &impl AstDatabase, 72 hygiene: &Hygiene,
72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>), 73 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
73 ) { 74 ) {
74 if let Some(tree) = item_src.ast.use_tree() { 75 if let Some(tree) = item_src.ast.use_tree() {
75 expand_use_tree(None, tree, &|| item_src.file_id.macro_crate(db), &mut cb); 76 expand_use_tree(None, tree, hygiene, &mut cb);
76 } 77 }
77 } 78 }
78 79
@@ -89,17 +90,12 @@ impl Path {
89 /// Converts an `ast::Path` to `Path`. Works with use trees. 90 /// Converts an `ast::Path` to `Path`. Works with use trees.
90 /// DEPRECATED: It does not handle `$crate` from macro call. 91 /// DEPRECATED: It does not handle `$crate` from macro call.
91 pub fn from_ast(path: ast::Path) -> Option<Path> { 92 pub fn from_ast(path: ast::Path) -> Option<Path> {
92 Path::parse(path, &|| None) 93 Path::from_src(path, &Hygiene::new_unhygienic())
93 } 94 }
94 95
95 /// Converts an `ast::Path` to `Path`. Works with use trees. 96 /// Converts an `ast::Path` to `Path`. Works with use trees.
96 /// It correctly handles `$crate` based path from macro call. 97 /// It correctly handles `$crate` based path from macro call.
97 pub fn from_src(source: Source<ast::Path>, db: &impl AstDatabase) -> Option<Path> { 98 pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
98 let file_id = source.file_id;
99 Path::parse(source.ast, &|| file_id.macro_crate(db))
100 }
101
102 fn parse(mut path: ast::Path, macro_crate: &impl Fn() -> Option<CrateId>) -> Option<Path> {
103 let mut kind = PathKind::Plain; 99 let mut kind = PathKind::Plain;
104 let mut segments = Vec::new(); 100 let mut segments = Vec::new();
105 loop { 101 loop {
@@ -110,26 +106,28 @@ impl Path {
110 } 106 }
111 107
112 match segment.kind()? { 108 match segment.kind()? {
113 ast::PathSegmentKind::Name(name) => { 109 ast::PathSegmentKind::Name(name_ref) => {
114 if name.text() == "$crate" { 110 // FIXME: this should just return name
115 if let Some(macro_crate) = macro_crate() { 111 match hygiene.name_ref_to_name(name_ref) {
116 kind = PathKind::DollarCrate(macro_crate); 112 Either::A(name) => {
113 let args = segment
114 .type_arg_list()
115 .and_then(GenericArgs::from_ast)
116 .or_else(|| {
117 GenericArgs::from_fn_like_path_ast(
118 segment.param_list(),
119 segment.ret_type(),
120 )
121 })
122 .map(Arc::new);
123 let segment = PathSegment { name, args_and_bindings: args };
124 segments.push(segment);
125 }
126 Either::B(crate_id) => {
127 kind = PathKind::DollarCrate(crate_id);
117 break; 128 break;
118 } 129 }
119 } 130 }
120
121 let args = segment
122 .type_arg_list()
123 .and_then(GenericArgs::from_ast)
124 .or_else(|| {
125 GenericArgs::from_fn_like_path_ast(
126 segment.param_list(),
127 segment.ret_type(),
128 )
129 })
130 .map(Arc::new);
131 let segment = PathSegment { name: name.as_name(), args_and_bindings: args };
132 segments.push(segment);
133 } 131 }
134 ast::PathSegmentKind::Type { type_ref, trait_ref } => { 132 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
135 assert!(path.qualifier().is_none()); // this can only occur at the first segment 133 assert!(path.qualifier().is_none()); // this can only occur at the first segment
@@ -143,7 +141,7 @@ impl Path {
143 } 141 }
144 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo 142 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
145 Some(trait_ref) => { 143 Some(trait_ref) => {
146 let path = Path::parse(trait_ref.path()?, macro_crate)?; 144 let path = Path::from_src(trait_ref.path()?, hygiene)?;
147 kind = path.kind; 145 kind = path.kind;
148 let mut prefix_segments = path.segments; 146 let mut prefix_segments = path.segments;
149 prefix_segments.reverse(); 147 prefix_segments.reverse();
@@ -294,7 +292,7 @@ impl From<Name> for Path {
294fn expand_use_tree( 292fn expand_use_tree(
295 prefix: Option<Path>, 293 prefix: Option<Path>,
296 tree: ast::UseTree, 294 tree: ast::UseTree,
297 macro_crate: &impl Fn() -> Option<CrateId>, 295 hygiene: &Hygiene,
298 cb: &mut impl FnMut(Path, &ast::UseTree, bool, Option<Name>), 296 cb: &mut impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
299) { 297) {
300 if let Some(use_tree_list) = tree.use_tree_list() { 298 if let Some(use_tree_list) = tree.use_tree_list() {
@@ -303,13 +301,13 @@ fn expand_use_tree(
303 None => prefix, 301 None => prefix,
304 // E.g. `use something::{inner}` (prefix is `None`, path is `something`) 302 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
305 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`) 303 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
306 Some(path) => match convert_path(prefix, path, macro_crate) { 304 Some(path) => match convert_path(prefix, path, hygiene) {
307 Some(it) => Some(it), 305 Some(it) => Some(it),
308 None => return, // FIXME: report errors somewhere 306 None => return, // FIXME: report errors somewhere
309 }, 307 },
310 }; 308 };
311 for child_tree in use_tree_list.use_trees() { 309 for child_tree in use_tree_list.use_trees() {
312 expand_use_tree(prefix.clone(), child_tree, macro_crate, cb); 310 expand_use_tree(prefix.clone(), child_tree, hygiene, cb);
313 } 311 }
314 } else { 312 } else {
315 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); 313 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name());
@@ -326,7 +324,7 @@ fn expand_use_tree(
326 } 324 }
327 } 325 }
328 } 326 }
329 if let Some(path) = convert_path(prefix, ast_path, macro_crate) { 327 if let Some(path) = convert_path(prefix, ast_path, hygiene) {
330 let is_glob = tree.has_star(); 328 let is_glob = tree.has_star();
331 cb(path, &tree, is_glob, alias) 329 cb(path, &tree, is_glob, alias)
332 } 330 }
@@ -336,37 +334,36 @@ fn expand_use_tree(
336 } 334 }
337} 335}
338 336
339fn convert_path( 337fn convert_path(prefix: Option<Path>, path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
340 prefix: Option<Path>,
341 path: ast::Path,
342 macro_crate: &impl Fn() -> Option<CrateId>,
343) -> Option<Path> {
344 let prefix = if let Some(qual) = path.qualifier() { 338 let prefix = if let Some(qual) = path.qualifier() {
345 Some(convert_path(prefix, qual, macro_crate)?) 339 Some(convert_path(prefix, qual, hygiene)?)
346 } else { 340 } else {
347 prefix 341 prefix
348 }; 342 };
349 343
350 let segment = path.segment()?; 344 let segment = path.segment()?;
351 let res = match segment.kind()? { 345 let res = match segment.kind()? {
352 ast::PathSegmentKind::Name(name) => { 346 ast::PathSegmentKind::Name(name_ref) => {
353 if name.text() == "$crate" { 347 match hygiene.name_ref_to_name(name_ref) {
354 if let Some(krate) = macro_crate() { 348 Either::A(name) => {
349 // no type args in use
350 let mut res = prefix.unwrap_or_else(|| Path {
351 kind: PathKind::Plain,
352 segments: Vec::with_capacity(1),
353 });
354 res.segments.push(PathSegment {
355 name,
356 args_and_bindings: None, // no type args in use
357 });
358 res
359 }
360 Either::B(crate_id) => {
355 return Some(Path::from_simple_segments( 361 return Some(Path::from_simple_segments(
356 PathKind::DollarCrate(krate), 362 PathKind::DollarCrate(crate_id),
357 iter::empty(), 363 iter::empty(),
358 )); 364 ))
359 } 365 }
360 } 366 }
361
362 // no type args in use
363 let mut res = prefix
364 .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) });
365 res.segments.push(PathSegment {
366 name: name.as_name(),
367 args_and_bindings: None, // no type args in use
368 });
369 res
370 } 367 }
371 ast::PathSegmentKind::CrateKw => { 368 ast::PathSegmentKind::CrateKw => {
372 if prefix.is_some() { 369 if prefix.is_some() {