diff options
-rw-r--r-- | crates/ra_hir_def/src/attr.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir_def/src/find_path.rs | 78 |
2 files changed, 87 insertions, 14 deletions
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 714a66b02..5a86af8ba 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs | |||
@@ -13,7 +13,8 @@ use ra_syntax::{ | |||
13 | use tt::Subtree; | 13 | use tt::Subtree; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | db::DefDatabase, path::ModPath, src::HasChildSource, src::HasSource, AdtId, AttrDefId, Lookup, | 16 | db::DefDatabase, nameres::ModuleSource, path::ModPath, src::HasChildSource, src::HasSource, |
17 | AdtId, AttrDefId, Lookup, | ||
17 | }; | 18 | }; |
18 | 19 | ||
19 | #[derive(Default, Debug, Clone, PartialEq, Eq)] | 20 | #[derive(Default, Debug, Clone, PartialEq, Eq)] |
@@ -37,11 +38,19 @@ impl Attrs { | |||
37 | match def { | 38 | match def { |
38 | AttrDefId::ModuleId(module) => { | 39 | AttrDefId::ModuleId(module) => { |
39 | let def_map = db.crate_def_map(module.krate); | 40 | let def_map = db.crate_def_map(module.krate); |
40 | let src = match def_map[module.local_id].declaration_source(db) { | 41 | let mod_data = &def_map[module.local_id]; |
41 | Some(it) => it, | 42 | match mod_data.declaration_source(db) { |
42 | None => return Attrs::default(), | 43 | Some(it) => { |
43 | }; | 44 | Attrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner)) |
44 | Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) | 45 | } |
46 | None => Attrs::from_attrs_owner( | ||
47 | db, | ||
48 | mod_data.definition_source(db).as_ref().map(|src| match src { | ||
49 | ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, | ||
50 | ModuleSource::Module(module) => module as &dyn AttrsOwner, | ||
51 | }), | ||
52 | ), | ||
53 | } | ||
45 | } | 54 | } |
46 | AttrDefId::FieldId(it) => { | 55 | AttrDefId::FieldId(it) => { |
47 | let src = it.parent.child_source(db); | 56 | let src = it.parent.child_source(db); |
@@ -106,7 +115,9 @@ pub struct Attr { | |||
106 | 115 | ||
107 | #[derive(Debug, Clone, PartialEq, Eq)] | 116 | #[derive(Debug, Clone, PartialEq, Eq)] |
108 | pub enum AttrInput { | 117 | pub enum AttrInput { |
118 | /// `#[attr = "string"]` | ||
109 | Literal(SmolStr), | 119 | Literal(SmolStr), |
120 | /// `#[attr(subtree)]` | ||
110 | TokenTree(Subtree), | 121 | TokenTree(Subtree), |
111 | } | 122 | } |
112 | 123 | ||
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs index 81eff5bfe..70dcb03e6 100644 --- a/crates/ra_hir_def/src/find_path.rs +++ b/crates/ra_hir_def/src/find_path.rs | |||
@@ -19,7 +19,7 @@ impl ModPath { | |||
19 | 19 | ||
20 | // When std library is present, paths starting with `std::` | 20 | // When std library is present, paths starting with `std::` |
21 | // should be preferred over paths starting with `core::` and `alloc::` | 21 | // should be preferred over paths starting with `core::` and `alloc::` |
22 | fn should_start_with_std(&self) -> bool { | 22 | fn can_start_with_std(&self) -> bool { |
23 | self.segments | 23 | self.segments |
24 | .first() | 24 | .first() |
25 | .filter(|&first_segment| { | 25 | .filter(|&first_segment| { |
@@ -132,6 +132,9 @@ fn find_path_inner( | |||
132 | } | 132 | } |
133 | 133 | ||
134 | // - otherwise, look for modules containing (reexporting) it and import it from one of those | 134 | // - otherwise, look for modules containing (reexporting) it and import it from one of those |
135 | let crate_root = ModuleId { local_id: def_map.root, krate: from.krate }; | ||
136 | let crate_attrs = db.attrs(crate_root.into()); | ||
137 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); | ||
135 | let importable_locations = find_importable_locations(db, item, from); | 138 | let importable_locations = find_importable_locations(db, item, from); |
136 | let mut best_path = None; | 139 | let mut best_path = None; |
137 | let mut best_path_len = max_len; | 140 | let mut best_path_len = max_len; |
@@ -147,21 +150,32 @@ fn find_path_inner( | |||
147 | }; | 150 | }; |
148 | path.segments.push(name); | 151 | path.segments.push(name); |
149 | 152 | ||
150 | let new_path = | 153 | let new_path = if let Some(best_path) = best_path { |
151 | if let Some(best_path) = best_path { select_best_path(best_path, path) } else { path }; | 154 | select_best_path(best_path, path, prefer_no_std) |
155 | } else { | ||
156 | path | ||
157 | }; | ||
152 | best_path_len = new_path.len(); | 158 | best_path_len = new_path.len(); |
153 | best_path = Some(new_path); | 159 | best_path = Some(new_path); |
154 | } | 160 | } |
155 | best_path | 161 | best_path |
156 | } | 162 | } |
157 | 163 | ||
158 | fn select_best_path(old_path: ModPath, new_path: ModPath) -> ModPath { | 164 | fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath { |
159 | if old_path.starts_with_std() && new_path.should_start_with_std() { | 165 | if old_path.starts_with_std() && new_path.can_start_with_std() { |
160 | tested_by!(prefer_std_paths); | 166 | tested_by!(prefer_std_paths); |
161 | old_path | 167 | if prefer_no_std { |
162 | } else if new_path.starts_with_std() && old_path.should_start_with_std() { | 168 | new_path |
169 | } else { | ||
170 | old_path | ||
171 | } | ||
172 | } else if new_path.starts_with_std() && old_path.can_start_with_std() { | ||
163 | tested_by!(prefer_std_paths); | 173 | tested_by!(prefer_std_paths); |
164 | new_path | 174 | if prefer_no_std { |
175 | old_path | ||
176 | } else { | ||
177 | new_path | ||
178 | } | ||
165 | } else if new_path.len() < old_path.len() { | 179 | } else if new_path.len() < old_path.len() { |
166 | new_path | 180 | new_path |
167 | } else { | 181 | } else { |
@@ -513,6 +527,54 @@ mod tests { | |||
513 | } | 527 | } |
514 | 528 | ||
515 | #[test] | 529 | #[test] |
530 | fn prefer_alloc_paths_over_std() { | ||
531 | covers!(prefer_std_paths); | ||
532 | let code = r#" | ||
533 | //- /main.rs crate:main deps:alloc,std | ||
534 | #![no_std] | ||
535 | |||
536 | <|> | ||
537 | |||
538 | //- /std.rs crate:std deps:alloc | ||
539 | |||
540 | pub mod sync { | ||
541 | pub use alloc::sync::Arc; | ||
542 | } | ||
543 | |||
544 | //- /zzz.rs crate:alloc | ||
545 | |||
546 | pub mod sync { | ||
547 | pub struct Arc; | ||
548 | } | ||
549 | "#; | ||
550 | check_found_path(code, "alloc::sync::Arc"); | ||
551 | } | ||
552 | |||
553 | #[test] | ||
554 | fn prefer_core_paths_over_std() { | ||
555 | covers!(prefer_std_paths); | ||
556 | let code = r#" | ||
557 | //- /main.rs crate:main deps:core,std | ||
558 | #![no_std] | ||
559 | |||
560 | <|> | ||
561 | |||
562 | //- /std.rs crate:std deps:core | ||
563 | |||
564 | pub mod fmt { | ||
565 | pub use core::fmt::Error; | ||
566 | } | ||
567 | |||
568 | //- /zzz.rs crate:core | ||
569 | |||
570 | pub mod fmt { | ||
571 | pub struct Error; | ||
572 | } | ||
573 | "#; | ||
574 | check_found_path(code, "core::fmt::Error"); | ||
575 | } | ||
576 | |||
577 | #[test] | ||
516 | fn prefer_shorter_paths_if_not_alloc() { | 578 | fn prefer_shorter_paths_if_not_alloc() { |
517 | let code = r#" | 579 | let code = r#" |
518 | //- /main.rs crate:main deps:megaalloc,std | 580 | //- /main.rs crate:main deps:megaalloc,std |