diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-02 08:20:50 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-02 08:20:50 +0000 |
commit | da3802b2ce4796461a9fff22f4e9c6fd890879b2 (patch) | |
tree | b3df38ae7b749178d854be9f2e6b16070a373216 /crates | |
parent | 4447019f4b5f24728bb7b91b161755ddb373c74c (diff) | |
parent | d8ef8acb47b1be92da97a2d5cd4334bceed5b919 (diff) |
Merge #725
725: Implement `use as` r=matklad a=flodiebold
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir/src/path.rs | 13 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 33 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 5 |
6 files changed, 83 insertions, 17 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 7ec6512b6..04cc693b3 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -251,10 +251,14 @@ where | |||
251 | }; | 251 | }; |
252 | } | 252 | } |
253 | for (import_id, import_data) in input.imports.iter() { | 253 | for (import_id, import_data) in input.imports.iter() { |
254 | if let Some(segment) = import_data.path.segments.iter().last() { | 254 | if let Some(last_segment) = import_data.path.segments.iter().last() { |
255 | if !import_data.is_glob { | 255 | if !import_data.is_glob { |
256 | let name = import_data | ||
257 | .alias | ||
258 | .clone() | ||
259 | .unwrap_or_else(|| last_segment.name.clone()); | ||
256 | module_items.items.insert( | 260 | module_items.items.insert( |
257 | segment.name.clone(), | 261 | name, |
258 | Resolution { | 262 | Resolution { |
259 | def: PerNs::none(), | 263 | def: PerNs::none(), |
260 | import: Some(import_id), | 264 | import: Some(import_id), |
@@ -319,19 +323,18 @@ where | |||
319 | 323 | ||
320 | if reached_fixedpoint == ReachedFixedPoint::Yes { | 324 | if reached_fixedpoint == ReachedFixedPoint::Yes { |
321 | let last_segment = import.path.segments.last().unwrap(); | 325 | let last_segment = import.path.segments.last().unwrap(); |
326 | let name = import | ||
327 | .alias | ||
328 | .clone() | ||
329 | .unwrap_or_else(|| last_segment.name.clone()); | ||
330 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def,); | ||
322 | self.update(module_id, |items| { | 331 | self.update(module_id, |items| { |
323 | let res = Resolution { | 332 | let res = Resolution { |
324 | def, | 333 | def, |
325 | import: Some(import_id), | 334 | import: Some(import_id), |
326 | }; | 335 | }; |
327 | items.items.insert(last_segment.name.clone(), res); | 336 | items.items.insert(name, res); |
328 | }); | 337 | }); |
329 | log::debug!( | ||
330 | "resolved import {:?} ({:?}) cross-source root to {:?}", | ||
331 | last_segment.name, | ||
332 | import, | ||
333 | def, | ||
334 | ); | ||
335 | } | 338 | } |
336 | reached_fixedpoint | 339 | reached_fixedpoint |
337 | } | 340 | } |
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 9a45fa61c..df87f520f 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -21,6 +21,7 @@ impl_arena_id!(ImportId); | |||
21 | #[derive(Debug, PartialEq, Eq)] | 21 | #[derive(Debug, PartialEq, Eq)] |
22 | pub(super) struct ImportData { | 22 | pub(super) struct ImportData { |
23 | pub(super) path: Path, | 23 | pub(super) path: Path, |
24 | pub(super) alias: Option<Name>, | ||
24 | pub(super) is_glob: bool, | 25 | pub(super) is_glob: bool, |
25 | } | 26 | } |
26 | 27 | ||
@@ -209,9 +210,10 @@ impl LoweredModule { | |||
209 | } | 210 | } |
210 | 211 | ||
211 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { | 212 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { |
212 | Path::expand_use_item(item, |path, segment| { | 213 | Path::expand_use_item(item, |path, segment, alias| { |
213 | let import = self.imports.alloc(ImportData { | 214 | let import = self.imports.alloc(ImportData { |
214 | path, | 215 | path, |
216 | alias, | ||
215 | is_glob: segment.is_none(), | 217 | is_glob: segment.is_none(), |
216 | }); | 218 | }); |
217 | if let Some(segment) = segment { | 219 | if let Some(segment) = segment { |
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index 0e0683db7..81c8a4f12 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -91,6 +91,30 @@ fn item_map_smoke_test() { | |||
91 | } | 91 | } |
92 | 92 | ||
93 | #[test] | 93 | #[test] |
94 | fn use_as() { | ||
95 | let (item_map, module_id) = item_map( | ||
96 | " | ||
97 | //- /lib.rs | ||
98 | mod foo; | ||
99 | |||
100 | use crate::foo::Baz as Foo; | ||
101 | <|> | ||
102 | |||
103 | //- /foo/mod.rs | ||
104 | pub struct Baz; | ||
105 | ", | ||
106 | ); | ||
107 | check_module_item_map( | ||
108 | &item_map, | ||
109 | module_id, | ||
110 | " | ||
111 | Foo: t v | ||
112 | foo: t | ||
113 | ", | ||
114 | ); | ||
115 | } | ||
116 | |||
117 | #[test] | ||
94 | fn use_trees() { | 118 | fn use_trees() { |
95 | let (item_map, module_id) = item_map( | 119 | let (item_map, module_id) = item_map( |
96 | " | 120 | " |
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index e13d84c57..cb0a04500 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{ast, AstNode}; | 3 | use ra_syntax::{ast::{self, NameOwner}, AstNode}; |
4 | 4 | ||
5 | use crate::{Name, AsName, type_ref::TypeRef}; | 5 | use crate::{Name, AsName, type_ref::TypeRef}; |
6 | 6 | ||
@@ -46,7 +46,7 @@ impl Path { | |||
46 | /// Calls `cb` with all paths, represented by this use item. | 46 | /// Calls `cb` with all paths, represented by this use item. |
47 | pub fn expand_use_item<'a>( | 47 | pub fn expand_use_item<'a>( |
48 | item: &'a ast::UseItem, | 48 | item: &'a ast::UseItem, |
49 | mut cb: impl FnMut(Path, Option<&'a ast::PathSegment>), | 49 | mut cb: impl FnMut(Path, Option<&'a ast::PathSegment>, Option<Name>), |
50 | ) { | 50 | ) { |
51 | if let Some(tree) = item.use_tree() { | 51 | if let Some(tree) = item.use_tree() { |
52 | expand_use_tree(None, tree, &mut cb); | 52 | expand_use_tree(None, tree, &mut cb); |
@@ -164,7 +164,7 @@ impl From<Name> for Path { | |||
164 | fn expand_use_tree<'a>( | 164 | fn expand_use_tree<'a>( |
165 | prefix: Option<Path>, | 165 | prefix: Option<Path>, |
166 | tree: &'a ast::UseTree, | 166 | tree: &'a ast::UseTree, |
167 | cb: &mut impl FnMut(Path, Option<&'a ast::PathSegment>), | 167 | cb: &mut impl FnMut(Path, Option<&'a ast::PathSegment>, Option<Name>), |
168 | ) { | 168 | ) { |
169 | if let Some(use_tree_list) = tree.use_tree_list() { | 169 | if let Some(use_tree_list) = tree.use_tree_list() { |
170 | let prefix = match tree.path() { | 170 | let prefix = match tree.path() { |
@@ -181,6 +181,7 @@ fn expand_use_tree<'a>( | |||
181 | expand_use_tree(prefix.clone(), child_tree, cb); | 181 | expand_use_tree(prefix.clone(), child_tree, cb); |
182 | } | 182 | } |
183 | } else { | 183 | } else { |
184 | let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); | ||
184 | if let Some(ast_path) = tree.path() { | 185 | if let Some(ast_path) = tree.path() { |
185 | // Handle self in a path. | 186 | // Handle self in a path. |
186 | // E.g. `use something::{self, <...>}` | 187 | // E.g. `use something::{self, <...>}` |
@@ -188,7 +189,7 @@ fn expand_use_tree<'a>( | |||
188 | if let Some(segment) = ast_path.segment() { | 189 | if let Some(segment) = ast_path.segment() { |
189 | if segment.kind() == Some(ast::PathSegmentKind::SelfKw) { | 190 | if segment.kind() == Some(ast::PathSegmentKind::SelfKw) { |
190 | if let Some(prefix) = prefix { | 191 | if let Some(prefix) = prefix { |
191 | cb(prefix, Some(segment)); | 192 | cb(prefix, Some(segment), alias); |
192 | return; | 193 | return; |
193 | } | 194 | } |
194 | } | 195 | } |
@@ -196,9 +197,9 @@ fn expand_use_tree<'a>( | |||
196 | } | 197 | } |
197 | if let Some(path) = convert_path(prefix, ast_path) { | 198 | if let Some(path) = convert_path(prefix, ast_path) { |
198 | if tree.has_star() { | 199 | if tree.has_star() { |
199 | cb(path, None) | 200 | cb(path, None, alias) |
200 | } else if let Some(segment) = ast_path.segment() { | 201 | } else if let Some(segment) = ast_path.segment() { |
201 | cb(path, Some(segment)) | 202 | cb(path, Some(segment), alias) |
202 | }; | 203 | }; |
203 | } | 204 | } |
204 | // TODO: report errors somewhere | 205 | // TODO: report errors somewhere |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index d0561c495..60480c699 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -17,6 +17,35 @@ use crate::{ | |||
17 | ast::{self, AstNode}, | 17 | ast::{self, AstNode}, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | // Alias | ||
21 | #[derive(Debug, PartialEq, Eq, Hash)] | ||
22 | #[repr(transparent)] | ||
23 | pub struct Alias { | ||
24 | pub(crate) syntax: SyntaxNode, | ||
25 | } | ||
26 | unsafe impl TransparentNewType for Alias { | ||
27 | type Repr = rowan::SyntaxNode<RaTypes>; | ||
28 | } | ||
29 | |||
30 | impl AstNode for Alias { | ||
31 | fn cast(syntax: &SyntaxNode) -> Option<&Self> { | ||
32 | match syntax.kind() { | ||
33 | ALIAS => Some(Alias::from_repr(syntax.into_repr())), | ||
34 | _ => None, | ||
35 | } | ||
36 | } | ||
37 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
38 | } | ||
39 | |||
40 | impl ToOwned for Alias { | ||
41 | type Owned = TreeArc<Alias>; | ||
42 | fn to_owned(&self) -> TreeArc<Alias> { TreeArc::cast(self.syntax.to_owned()) } | ||
43 | } | ||
44 | |||
45 | |||
46 | impl ast::NameOwner for Alias {} | ||
47 | impl Alias {} | ||
48 | |||
20 | // ArgList | 49 | // ArgList |
21 | #[derive(Debug, PartialEq, Eq, Hash)] | 50 | #[derive(Debug, PartialEq, Eq, Hash)] |
22 | #[repr(transparent)] | 51 | #[repr(transparent)] |
@@ -4176,6 +4205,10 @@ impl UseTree { | |||
4176 | pub fn use_tree_list(&self) -> Option<&UseTreeList> { | 4205 | pub fn use_tree_list(&self) -> Option<&UseTreeList> { |
4177 | super::child_opt(self) | 4206 | super::child_opt(self) |
4178 | } | 4207 | } |
4208 | |||
4209 | pub fn alias(&self) -> Option<&Alias> { | ||
4210 | super::child_opt(self) | ||
4211 | } | ||
4179 | } | 4212 | } |
4180 | 4213 | ||
4181 | // UseTreeList | 4214 | // UseTreeList |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 47334bdf0..a2ccd7cb9 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -593,7 +593,10 @@ Grammar( | |||
593 | options: [ "UseTree" ] | 593 | options: [ "UseTree" ] |
594 | ), | 594 | ), |
595 | "UseTree": ( | 595 | "UseTree": ( |
596 | options: [ "Path", "UseTreeList" ] | 596 | options: [ "Path", "UseTreeList", "Alias" ] |
597 | ), | ||
598 | "Alias": ( | ||
599 | traits: ["NameOwner"], | ||
597 | ), | 600 | ), |
598 | "UseTreeList": ( | 601 | "UseTreeList": ( |
599 | collections: [["use_trees", "UseTree"]] | 602 | collections: [["use_trees", "UseTree"]] |