diff options
30 files changed, 831 insertions, 177 deletions
diff --git a/Cargo.lock b/Cargo.lock index 7d2911076..b63b5ae13 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -10,7 +10,7 @@ dependencies = [ | |||
10 | 10 | ||
11 | [[package]] | 11 | [[package]] |
12 | name = "anyhow" | 12 | name = "anyhow" |
13 | version = "1.0.25" | 13 | version = "1.0.26" |
14 | source = "registry+https://github.com/rust-lang/crates.io-index" | 14 | source = "registry+https://github.com/rust-lang/crates.io-index" |
15 | 15 | ||
16 | [[package]] | 16 | [[package]] |
@@ -237,7 +237,7 @@ dependencies = [ | |||
237 | "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | 237 | "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", |
238 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", | 238 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", |
239 | "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | 239 | "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", |
240 | "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | 240 | "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", |
241 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | 241 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", |
242 | ] | 242 | ] |
243 | 243 | ||
@@ -273,9 +273,10 @@ dependencies = [ | |||
273 | 273 | ||
274 | [[package]] | 274 | [[package]] |
275 | name = "crossbeam-queue" | 275 | name = "crossbeam-queue" |
276 | version = "0.2.0" | 276 | version = "0.2.1" |
277 | source = "registry+https://github.com/rust-lang/crates.io-index" | 277 | source = "registry+https://github.com/rust-lang/crates.io-index" |
278 | dependencies = [ | 278 | dependencies = [ |
279 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", | ||
279 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | 280 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", |
280 | ] | 281 | ] |
281 | 282 | ||
@@ -1349,7 +1350,7 @@ version = "1.7.0" | |||
1349 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1350 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1350 | dependencies = [ | 1351 | dependencies = [ |
1351 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", | 1352 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", |
1352 | "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1353 | "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1353 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1354 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1354 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1355 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1355 | "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1356 | "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -1767,7 +1768,7 @@ dependencies = [ | |||
1767 | name = "xtask" | 1768 | name = "xtask" |
1768 | version = "0.1.0" | 1769 | version = "0.1.0" |
1769 | dependencies = [ | 1770 | dependencies = [ |
1770 | "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", | 1771 | "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", |
1771 | "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1772 | "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1772 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", | 1773 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", |
1773 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | 1774 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -1786,7 +1787,7 @@ dependencies = [ | |||
1786 | 1787 | ||
1787 | [metadata] | 1788 | [metadata] |
1788 | "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" | 1789 | "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" |
1789 | "checksum anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" | 1790 | "checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" |
1790 | "checksum anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" | 1791 | "checksum anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" |
1791 | "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" | 1792 | "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" |
1792 | "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" | 1793 | "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" |
@@ -1817,7 +1818,7 @@ dependencies = [ | |||
1817 | "checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" | 1818 | "checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" |
1818 | "checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" | 1819 | "checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" |
1819 | "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" | 1820 | "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" |
1820 | "checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" | 1821 | "checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" |
1821 | "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" | 1822 | "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" |
1822 | "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" | 1823 | "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" |
1823 | "checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" | 1824 | "checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" |
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 993aebc47..28152f724 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs | |||
@@ -46,7 +46,7 @@ pub(crate) enum Assist { | |||
46 | /// | 46 | /// |
47 | /// Note, however, that we don't actually use such two-phase logic at the | 47 | /// Note, however, that we don't actually use such two-phase logic at the |
48 | /// moment, because the LSP API is pretty awkward in this place, and it's much | 48 | /// moment, because the LSP API is pretty awkward in this place, and it's much |
49 | /// easier to just compute the edit eagerly :-)#[derive(Debug, Clone)] | 49 | /// easier to just compute the edit eagerly :-) |
50 | #[derive(Debug)] | 50 | #[derive(Debug)] |
51 | pub(crate) struct AssistCtx<'a, DB> { | 51 | pub(crate) struct AssistCtx<'a, DB> { |
52 | pub(crate) db: &'a DB, | 52 | pub(crate) db: &'a DB, |
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs index cef669cb5..bc49e71fe 100644 --- a/crates/ra_assists/src/assists/add_missing_impl_members.rs +++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | use std::collections::HashMap; | ||
2 | |||
1 | use hir::{db::HirDatabase, HasSource}; | 3 | use hir::{db::HirDatabase, HasSource}; |
2 | use ra_syntax::{ | 4 | use ra_syntax::{ |
3 | ast::{self, edit, make, AstNode, NameOwner}, | 5 | ast::{self, edit, make, AstNode, NameOwner}, |
@@ -17,26 +19,26 @@ enum AddMissingImplMembersMode { | |||
17 | // Adds scaffold for required impl members. | 19 | // Adds scaffold for required impl members. |
18 | // | 20 | // |
19 | // ``` | 21 | // ``` |
20 | // trait T { | 22 | // trait Trait<T> { |
21 | // Type X; | 23 | // Type X; |
22 | // fn foo(&self); | 24 | // fn foo(&self) -> T; |
23 | // fn bar(&self) {} | 25 | // fn bar(&self) {} |
24 | // } | 26 | // } |
25 | // | 27 | // |
26 | // impl T for () {<|> | 28 | // impl Trait<u32> for () {<|> |
27 | // | 29 | // |
28 | // } | 30 | // } |
29 | // ``` | 31 | // ``` |
30 | // -> | 32 | // -> |
31 | // ``` | 33 | // ``` |
32 | // trait T { | 34 | // trait Trait<T> { |
33 | // Type X; | 35 | // Type X; |
34 | // fn foo(&self); | 36 | // fn foo(&self) -> T; |
35 | // fn bar(&self) {} | 37 | // fn bar(&self) {} |
36 | // } | 38 | // } |
37 | // | 39 | // |
38 | // impl T for () { | 40 | // impl Trait<u32> for () { |
39 | // fn foo(&self) { unimplemented!() } | 41 | // fn foo(&self) -> u32 { unimplemented!() } |
40 | // | 42 | // |
41 | // } | 43 | // } |
42 | // ``` | 44 | // ``` |
@@ -54,13 +56,13 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Opti | |||
54 | // Adds scaffold for overriding default impl members. | 56 | // Adds scaffold for overriding default impl members. |
55 | // | 57 | // |
56 | // ``` | 58 | // ``` |
57 | // trait T { | 59 | // trait Trait { |
58 | // Type X; | 60 | // Type X; |
59 | // fn foo(&self); | 61 | // fn foo(&self); |
60 | // fn bar(&self) {} | 62 | // fn bar(&self) {} |
61 | // } | 63 | // } |
62 | // | 64 | // |
63 | // impl T for () { | 65 | // impl Trait for () { |
64 | // Type X = (); | 66 | // Type X = (); |
65 | // fn foo(&self) {}<|> | 67 | // fn foo(&self) {}<|> |
66 | // | 68 | // |
@@ -68,13 +70,13 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Opti | |||
68 | // ``` | 70 | // ``` |
69 | // -> | 71 | // -> |
70 | // ``` | 72 | // ``` |
71 | // trait T { | 73 | // trait Trait { |
72 | // Type X; | 74 | // Type X; |
73 | // fn foo(&self); | 75 | // fn foo(&self); |
74 | // fn bar(&self) {} | 76 | // fn bar(&self) {} |
75 | // } | 77 | // } |
76 | // | 78 | // |
77 | // impl T for () { | 79 | // impl Trait for () { |
78 | // Type X = (); | 80 | // Type X = (); |
79 | // fn foo(&self) {} | 81 | // fn foo(&self) {} |
80 | // fn bar(&self) {} | 82 | // fn bar(&self) {} |
@@ -99,7 +101,7 @@ fn add_missing_impl_members_inner( | |||
99 | let impl_node = ctx.find_node_at_offset::<ast::ImplBlock>()?; | 101 | let impl_node = ctx.find_node_at_offset::<ast::ImplBlock>()?; |
100 | let impl_item_list = impl_node.item_list()?; | 102 | let impl_item_list = impl_node.item_list()?; |
101 | 103 | ||
102 | let trait_def = { | 104 | let (trait_, trait_def) = { |
103 | let analyzer = ctx.source_analyzer(impl_node.syntax(), None); | 105 | let analyzer = ctx.source_analyzer(impl_node.syntax(), None); |
104 | 106 | ||
105 | resolve_target_trait_def(ctx.db, &analyzer, &impl_node)? | 107 | resolve_target_trait_def(ctx.db, &analyzer, &impl_node)? |
@@ -132,10 +134,25 @@ fn add_missing_impl_members_inner( | |||
132 | return None; | 134 | return None; |
133 | } | 135 | } |
134 | 136 | ||
137 | let file_id = ctx.frange.file_id; | ||
138 | let db = ctx.db; | ||
139 | |||
135 | ctx.add_assist(AssistId(assist_id), label, |edit| { | 140 | ctx.add_assist(AssistId(assist_id), label, |edit| { |
136 | let n_existing_items = impl_item_list.impl_items().count(); | 141 | let n_existing_items = impl_item_list.impl_items().count(); |
142 | let substs = get_syntactic_substs(impl_node).unwrap_or_default(); | ||
143 | let generic_def: hir::GenericDef = trait_.into(); | ||
144 | let substs_by_param: HashMap<_, _> = generic_def | ||
145 | .params(db) | ||
146 | .into_iter() | ||
147 | // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky | ||
148 | .skip(1) | ||
149 | .zip(substs.into_iter()) | ||
150 | .collect(); | ||
137 | let items = missing_items | 151 | let items = missing_items |
138 | .into_iter() | 152 | .into_iter() |
153 | .map(|it| { | ||
154 | substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param) | ||
155 | }) | ||
139 | .map(|it| match it { | 156 | .map(|it| match it { |
140 | ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), | 157 | ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), |
141 | _ => it, | 158 | _ => it, |
@@ -160,13 +177,63 @@ fn add_body(fn_def: ast::FnDef) -> ast::FnDef { | |||
160 | } | 177 | } |
161 | } | 178 | } |
162 | 179 | ||
180 | // FIXME: It would probably be nicer if we could get this via HIR (i.e. get the | ||
181 | // trait ref, and then go from the types in the substs back to the syntax) | ||
182 | // FIXME: This should be a general utility (not even just for assists) | ||
183 | fn get_syntactic_substs(impl_block: ast::ImplBlock) -> Option<Vec<ast::TypeRef>> { | ||
184 | let target_trait = impl_block.target_trait()?; | ||
185 | let path_type = match target_trait { | ||
186 | ast::TypeRef::PathType(path) => path, | ||
187 | _ => return None, | ||
188 | }; | ||
189 | let type_arg_list = path_type.path()?.segment()?.type_arg_list()?; | ||
190 | let mut result = Vec::new(); | ||
191 | for type_arg in type_arg_list.type_args() { | ||
192 | let type_arg: ast::TypeArg = type_arg; | ||
193 | result.push(type_arg.type_ref()?); | ||
194 | } | ||
195 | Some(result) | ||
196 | } | ||
197 | |||
198 | // FIXME: This should be a general utility (not even just for assists) | ||
199 | fn substitute_type_params<N: AstNode>( | ||
200 | db: &impl HirDatabase, | ||
201 | node: hir::InFile<N>, | ||
202 | substs: &HashMap<hir::TypeParam, ast::TypeRef>, | ||
203 | ) -> N { | ||
204 | let type_param_replacements = node | ||
205 | .value | ||
206 | .syntax() | ||
207 | .descendants() | ||
208 | .filter_map(ast::TypeRef::cast) | ||
209 | .filter_map(|n| { | ||
210 | let path = match &n { | ||
211 | ast::TypeRef::PathType(path_type) => path_type.path()?, | ||
212 | _ => return None, | ||
213 | }; | ||
214 | let analyzer = hir::SourceAnalyzer::new(db, node.with_value(n.syntax()), None); | ||
215 | let resolution = analyzer.resolve_path(db, &path)?; | ||
216 | match resolution { | ||
217 | hir::PathResolution::TypeParam(tp) => Some((n, substs.get(&tp)?.clone())), | ||
218 | _ => None, | ||
219 | } | ||
220 | }) | ||
221 | .collect::<Vec<_>>(); | ||
222 | |||
223 | if type_param_replacements.is_empty() { | ||
224 | node.value | ||
225 | } else { | ||
226 | edit::replace_descendants(&node.value, type_param_replacements.into_iter()) | ||
227 | } | ||
228 | } | ||
229 | |||
163 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being | 230 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being |
164 | /// implemented) to a `ast::TraitDef`. | 231 | /// implemented) to a `ast::TraitDef`. |
165 | fn resolve_target_trait_def( | 232 | fn resolve_target_trait_def( |
166 | db: &impl HirDatabase, | 233 | db: &impl HirDatabase, |
167 | analyzer: &hir::SourceAnalyzer, | 234 | analyzer: &hir::SourceAnalyzer, |
168 | impl_block: &ast::ImplBlock, | 235 | impl_block: &ast::ImplBlock, |
169 | ) -> Option<ast::TraitDef> { | 236 | ) -> Option<(hir::Trait, ast::TraitDef)> { |
170 | let ast_path = impl_block | 237 | let ast_path = impl_block |
171 | .target_trait() | 238 | .target_trait() |
172 | .map(|it| it.syntax().clone()) | 239 | .map(|it| it.syntax().clone()) |
@@ -174,7 +241,9 @@ fn resolve_target_trait_def( | |||
174 | .path()?; | 241 | .path()?; |
175 | 242 | ||
176 | match analyzer.resolve_path(db, &ast_path) { | 243 | match analyzer.resolve_path(db, &ast_path) { |
177 | Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).value), | 244 | Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => { |
245 | Some((def, def.source(db).value)) | ||
246 | } | ||
178 | _ => None, | 247 | _ => None, |
179 | } | 248 | } |
180 | } | 249 | } |
@@ -281,6 +350,40 @@ impl Foo for S { | |||
281 | } | 350 | } |
282 | 351 | ||
283 | #[test] | 352 | #[test] |
353 | fn fill_in_type_params_1() { | ||
354 | check_assist( | ||
355 | add_missing_impl_members, | ||
356 | " | ||
357 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | ||
358 | struct S; | ||
359 | impl Foo<u32> for S { <|> }", | ||
360 | " | ||
361 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | ||
362 | struct S; | ||
363 | impl Foo<u32> for S { | ||
364 | <|>fn foo(&self, t: u32) -> &u32 { unimplemented!() } | ||
365 | }", | ||
366 | ); | ||
367 | } | ||
368 | |||
369 | #[test] | ||
370 | fn fill_in_type_params_2() { | ||
371 | check_assist( | ||
372 | add_missing_impl_members, | ||
373 | " | ||
374 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | ||
375 | struct S; | ||
376 | impl<U> Foo<U> for S { <|> }", | ||
377 | " | ||
378 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | ||
379 | struct S; | ||
380 | impl<U> Foo<U> for S { | ||
381 | <|>fn foo(&self, t: U) -> &U { unimplemented!() } | ||
382 | }", | ||
383 | ); | ||
384 | } | ||
385 | |||
386 | #[test] | ||
284 | fn test_cursor_after_empty_impl_block() { | 387 | fn test_cursor_after_empty_impl_block() { |
285 | check_assist( | 388 | check_assist( |
286 | add_missing_impl_members, | 389 | add_missing_impl_members, |
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 4586eeb59..7d84dc8fb 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
@@ -101,26 +101,26 @@ fn doctest_add_impl_default_members() { | |||
101 | check( | 101 | check( |
102 | "add_impl_default_members", | 102 | "add_impl_default_members", |
103 | r#####" | 103 | r#####" |
104 | trait T { | 104 | trait Trait { |
105 | Type X; | 105 | Type X; |
106 | fn foo(&self); | 106 | fn foo(&self); |
107 | fn bar(&self) {} | 107 | fn bar(&self) {} |
108 | } | 108 | } |
109 | 109 | ||
110 | impl T for () { | 110 | impl Trait for () { |
111 | Type X = (); | 111 | Type X = (); |
112 | fn foo(&self) {}<|> | 112 | fn foo(&self) {}<|> |
113 | 113 | ||
114 | } | 114 | } |
115 | "#####, | 115 | "#####, |
116 | r#####" | 116 | r#####" |
117 | trait T { | 117 | trait Trait { |
118 | Type X; | 118 | Type X; |
119 | fn foo(&self); | 119 | fn foo(&self); |
120 | fn bar(&self) {} | 120 | fn bar(&self) {} |
121 | } | 121 | } |
122 | 122 | ||
123 | impl T for () { | 123 | impl Trait for () { |
124 | Type X = (); | 124 | Type X = (); |
125 | fn foo(&self) {} | 125 | fn foo(&self) {} |
126 | fn bar(&self) {} | 126 | fn bar(&self) {} |
@@ -135,25 +135,25 @@ fn doctest_add_impl_missing_members() { | |||
135 | check( | 135 | check( |
136 | "add_impl_missing_members", | 136 | "add_impl_missing_members", |
137 | r#####" | 137 | r#####" |
138 | trait T { | 138 | trait Trait<T> { |
139 | Type X; | 139 | Type X; |
140 | fn foo(&self); | 140 | fn foo(&self) -> T; |
141 | fn bar(&self) {} | 141 | fn bar(&self) {} |
142 | } | 142 | } |
143 | 143 | ||
144 | impl T for () {<|> | 144 | impl Trait<u32> for () {<|> |
145 | 145 | ||
146 | } | 146 | } |
147 | "#####, | 147 | "#####, |
148 | r#####" | 148 | r#####" |
149 | trait T { | 149 | trait Trait<T> { |
150 | Type X; | 150 | Type X; |
151 | fn foo(&self); | 151 | fn foo(&self) -> T; |
152 | fn bar(&self) {} | 152 | fn bar(&self) {} |
153 | } | 153 | } |
154 | 154 | ||
155 | impl T for () { | 155 | impl Trait<u32> for () { |
156 | fn foo(&self) { unimplemented!() } | 156 | fn foo(&self) -> u32 { unimplemented!() } |
157 | 157 | ||
158 | } | 158 | } |
159 | "#####, | 159 | "#####, |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index bcfc0d03e..488f74cfb 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -118,7 +118,7 @@ impl_froms!( | |||
118 | BuiltinType | 118 | BuiltinType |
119 | ); | 119 | ); |
120 | 120 | ||
121 | pub use hir_def::attr::Attrs; | 121 | pub use hir_def::{attr::Attrs, visibility::Visibility}; |
122 | 122 | ||
123 | impl Module { | 123 | impl Module { |
124 | pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module { | 124 | pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module { |
@@ -255,6 +255,15 @@ impl StructField { | |||
255 | } | 255 | } |
256 | } | 256 | } |
257 | 257 | ||
258 | impl HasVisibility for StructField { | ||
259 | fn visibility(&self, db: &impl HirDatabase) -> Visibility { | ||
260 | let variant_data = self.parent.variant_data(db); | ||
261 | let visibility = &variant_data.fields()[self.id].visibility; | ||
262 | let parent_id: hir_def::VariantId = self.parent.into(); | ||
263 | visibility.resolve(db, &parent_id.resolver(db)) | ||
264 | } | ||
265 | } | ||
266 | |||
258 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 267 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
259 | pub struct Struct { | 268 | pub struct Struct { |
260 | pub(crate) id: StructId, | 269 | pub(crate) id: StructId, |
@@ -644,6 +653,17 @@ impl_froms!( | |||
644 | Const | 653 | Const |
645 | ); | 654 | ); |
646 | 655 | ||
656 | impl GenericDef { | ||
657 | pub fn params(self, db: &impl HirDatabase) -> Vec<TypeParam> { | ||
658 | let generics: Arc<hir_def::generics::GenericParams> = db.generic_params(self.into()); | ||
659 | generics | ||
660 | .types | ||
661 | .iter() | ||
662 | .map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } }) | ||
663 | .collect() | ||
664 | } | ||
665 | } | ||
666 | |||
647 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 667 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
648 | pub struct Local { | 668 | pub struct Local { |
649 | pub(crate) parent: DefWithBody, | 669 | pub(crate) parent: DefWithBody, |
@@ -1030,3 +1050,11 @@ impl<T: Into<AttrDef> + Copy> Docs for T { | |||
1030 | db.documentation(def.into()) | 1050 | db.documentation(def.into()) |
1031 | } | 1051 | } |
1032 | } | 1052 | } |
1053 | |||
1054 | pub trait HasVisibility { | ||
1055 | fn visibility(&self, db: &impl HirDatabase) -> Visibility; | ||
1056 | fn is_visible_from(&self, db: &impl HirDatabase, module: Module) -> bool { | ||
1057 | let vis = self.visibility(db); | ||
1058 | vis.is_visible_from(db, module.id) | ||
1059 | } | ||
1060 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 0008a8858..3d13978d4 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -40,8 +40,8 @@ mod from_source; | |||
40 | pub use crate::{ | 40 | pub use crate::{ |
41 | code_model::{ | 41 | code_model::{ |
42 | Adt, AssocItem, AttrDef, Const, Crate, CrateDependency, DefWithBody, Docs, Enum, | 42 | Adt, AssocItem, AttrDef, Const, Crate, CrateDependency, DefWithBody, Docs, Enum, |
43 | EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Local, MacroDef, | 43 | EnumVariant, FieldSource, Function, GenericDef, HasAttrs, HasVisibility, ImplBlock, Local, |
44 | Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, | 44 | MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, |
45 | TypeParam, Union, VariantDef, | 45 | TypeParam, Union, VariantDef, |
46 | }, | 46 | }, |
47 | from_source::FromSource, | 47 | from_source::FromSource, |
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index d9ea693e3..aac5f3e15 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -9,11 +9,12 @@ use hir_expand::{ | |||
9 | }; | 9 | }; |
10 | use ra_arena::{map::ArenaMap, Arena}; | 10 | use ra_arena::{map::ArenaMap, Arena}; |
11 | use ra_prof::profile; | 11 | use ra_prof::profile; |
12 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | 12 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, type_ref::TypeRef, EnumId, | 15 | db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, type_ref::TypeRef, |
16 | LocalEnumVariantId, LocalStructFieldId, Lookup, StructId, UnionId, VariantId, | 16 | visibility::RawVisibility, EnumId, LocalEnumVariantId, LocalStructFieldId, Lookup, StructId, |
17 | UnionId, VariantId, | ||
17 | }; | 18 | }; |
18 | 19 | ||
19 | /// Note that we use `StructData` for unions as well! | 20 | /// Note that we use `StructData` for unions as well! |
@@ -47,13 +48,14 @@ pub enum VariantData { | |||
47 | pub struct StructFieldData { | 48 | pub struct StructFieldData { |
48 | pub name: Name, | 49 | pub name: Name, |
49 | pub type_ref: TypeRef, | 50 | pub type_ref: TypeRef, |
51 | pub visibility: RawVisibility, | ||
50 | } | 52 | } |
51 | 53 | ||
52 | impl StructData { | 54 | impl StructData { |
53 | pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc<StructData> { | 55 | pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc<StructData> { |
54 | let src = id.lookup(db).source(db); | 56 | let src = id.lookup(db).source(db); |
55 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 57 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
56 | let variant_data = VariantData::new(src.value.kind()); | 58 | let variant_data = VariantData::new(db, src.map(|s| s.kind())); |
57 | let variant_data = Arc::new(variant_data); | 59 | let variant_data = Arc::new(variant_data); |
58 | Arc::new(StructData { name, variant_data }) | 60 | Arc::new(StructData { name, variant_data }) |
59 | } | 61 | } |
@@ -61,10 +63,12 @@ impl StructData { | |||
61 | let src = id.lookup(db).source(db); | 63 | let src = id.lookup(db).source(db); |
62 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 64 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
63 | let variant_data = VariantData::new( | 65 | let variant_data = VariantData::new( |
64 | src.value | 66 | db, |
65 | .record_field_def_list() | 67 | src.map(|s| { |
66 | .map(ast::StructKind::Record) | 68 | s.record_field_def_list() |
67 | .unwrap_or(ast::StructKind::Unit), | 69 | .map(ast::StructKind::Record) |
70 | .unwrap_or(ast::StructKind::Unit) | ||
71 | }), | ||
68 | ); | 72 | ); |
69 | let variant_data = Arc::new(variant_data); | 73 | let variant_data = Arc::new(variant_data); |
70 | Arc::new(StructData { name, variant_data }) | 74 | Arc::new(StructData { name, variant_data }) |
@@ -77,7 +81,7 @@ impl EnumData { | |||
77 | let src = e.lookup(db).source(db); | 81 | let src = e.lookup(db).source(db); |
78 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 82 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
79 | let mut trace = Trace::new_for_arena(); | 83 | let mut trace = Trace::new_for_arena(); |
80 | lower_enum(&mut trace, &src.value); | 84 | lower_enum(db, &mut trace, &src); |
81 | Arc::new(EnumData { name, variants: trace.into_arena() }) | 85 | Arc::new(EnumData { name, variants: trace.into_arena() }) |
82 | } | 86 | } |
83 | 87 | ||
@@ -93,30 +97,31 @@ impl HasChildSource for EnumId { | |||
93 | fn child_source(&self, db: &impl DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { | 97 | fn child_source(&self, db: &impl DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { |
94 | let src = self.lookup(db).source(db); | 98 | let src = self.lookup(db).source(db); |
95 | let mut trace = Trace::new_for_map(); | 99 | let mut trace = Trace::new_for_map(); |
96 | lower_enum(&mut trace, &src.value); | 100 | lower_enum(db, &mut trace, &src); |
97 | src.with_value(trace.into_map()) | 101 | src.with_value(trace.into_map()) |
98 | } | 102 | } |
99 | } | 103 | } |
100 | 104 | ||
101 | fn lower_enum( | 105 | fn lower_enum( |
106 | db: &impl DefDatabase, | ||
102 | trace: &mut Trace<LocalEnumVariantId, EnumVariantData, ast::EnumVariant>, | 107 | trace: &mut Trace<LocalEnumVariantId, EnumVariantData, ast::EnumVariant>, |
103 | ast: &ast::EnumDef, | 108 | ast: &InFile<ast::EnumDef>, |
104 | ) { | 109 | ) { |
105 | for var in ast.variant_list().into_iter().flat_map(|it| it.variants()) { | 110 | for var in ast.value.variant_list().into_iter().flat_map(|it| it.variants()) { |
106 | trace.alloc( | 111 | trace.alloc( |
107 | || var.clone(), | 112 | || var.clone(), |
108 | || EnumVariantData { | 113 | || EnumVariantData { |
109 | name: var.name().map_or_else(Name::missing, |it| it.as_name()), | 114 | name: var.name().map_or_else(Name::missing, |it| it.as_name()), |
110 | variant_data: Arc::new(VariantData::new(var.kind())), | 115 | variant_data: Arc::new(VariantData::new(db, ast.with_value(var.kind()))), |
111 | }, | 116 | }, |
112 | ); | 117 | ); |
113 | } | 118 | } |
114 | } | 119 | } |
115 | 120 | ||
116 | impl VariantData { | 121 | impl VariantData { |
117 | fn new(flavor: ast::StructKind) -> Self { | 122 | fn new(db: &impl DefDatabase, flavor: InFile<ast::StructKind>) -> Self { |
118 | let mut trace = Trace::new_for_arena(); | 123 | let mut trace = Trace::new_for_arena(); |
119 | match lower_struct(&mut trace, &flavor) { | 124 | match lower_struct(db, &mut trace, &flavor) { |
120 | StructKind::Tuple => VariantData::Tuple(trace.into_arena()), | 125 | StructKind::Tuple => VariantData::Tuple(trace.into_arena()), |
121 | StructKind::Record => VariantData::Record(trace.into_arena()), | 126 | StructKind::Record => VariantData::Record(trace.into_arena()), |
122 | StructKind::Unit => VariantData::Unit, | 127 | StructKind::Unit => VariantData::Unit, |
@@ -163,7 +168,7 @@ impl HasChildSource for VariantId { | |||
163 | }), | 168 | }), |
164 | }; | 169 | }; |
165 | let mut trace = Trace::new_for_map(); | 170 | let mut trace = Trace::new_for_map(); |
166 | lower_struct(&mut trace, &src.value); | 171 | lower_struct(db, &mut trace, &src); |
167 | src.with_value(trace.into_map()) | 172 | src.with_value(trace.into_map()) |
168 | } | 173 | } |
169 | } | 174 | } |
@@ -175,14 +180,15 @@ enum StructKind { | |||
175 | } | 180 | } |
176 | 181 | ||
177 | fn lower_struct( | 182 | fn lower_struct( |
183 | db: &impl DefDatabase, | ||
178 | trace: &mut Trace< | 184 | trace: &mut Trace< |
179 | LocalStructFieldId, | 185 | LocalStructFieldId, |
180 | StructFieldData, | 186 | StructFieldData, |
181 | Either<ast::TupleFieldDef, ast::RecordFieldDef>, | 187 | Either<ast::TupleFieldDef, ast::RecordFieldDef>, |
182 | >, | 188 | >, |
183 | ast: &ast::StructKind, | 189 | ast: &InFile<ast::StructKind>, |
184 | ) -> StructKind { | 190 | ) -> StructKind { |
185 | match ast { | 191 | match &ast.value { |
186 | ast::StructKind::Tuple(fl) => { | 192 | ast::StructKind::Tuple(fl) => { |
187 | for (i, fd) in fl.fields().enumerate() { | 193 | for (i, fd) in fl.fields().enumerate() { |
188 | trace.alloc( | 194 | trace.alloc( |
@@ -190,6 +196,7 @@ fn lower_struct( | |||
190 | || StructFieldData { | 196 | || StructFieldData { |
191 | name: Name::new_tuple_field(i), | 197 | name: Name::new_tuple_field(i), |
192 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), | 198 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), |
199 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | ||
193 | }, | 200 | }, |
194 | ); | 201 | ); |
195 | } | 202 | } |
@@ -202,6 +209,7 @@ fn lower_struct( | |||
202 | || StructFieldData { | 209 | || StructFieldData { |
203 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), | 210 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), |
204 | type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), | 211 | type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), |
212 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | ||
205 | }, | 213 | }, |
206 | ); | 214 | ); |
207 | } | 215 | } |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 5323af097..fc3a028e0 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -543,7 +543,10 @@ where | |||
543 | }; | 543 | }; |
544 | self.body.item_scope.define_def(def); | 544 | self.body.item_scope.define_def(def); |
545 | if let Some(name) = name { | 545 | if let Some(name) = name { |
546 | self.body.item_scope.push_res(name.as_name(), def.into()); | 546 | let vis = crate::visibility::Visibility::Public; // FIXME determine correctly |
547 | self.body | ||
548 | .item_scope | ||
549 | .push_res(name.as_name(), crate::per_ns::PerNs::from_def(def, vis)); | ||
547 | } | 550 | } |
548 | } | 551 | } |
549 | } | 552 | } |
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index b0288ee8d..fe7bb9779 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -5,7 +5,10 @@ use hir_expand::name::Name; | |||
5 | use once_cell::sync::Lazy; | 5 | use once_cell::sync::Lazy; |
6 | use rustc_hash::FxHashMap; | 6 | use rustc_hash::FxHashMap; |
7 | 7 | ||
8 | use crate::{per_ns::PerNs, AdtId, BuiltinType, ImplId, MacroDefId, ModuleDefId, TraitId}; | 8 | use crate::{ |
9 | per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId, MacroDefId, ModuleDefId, | ||
10 | TraitId, | ||
11 | }; | ||
9 | 12 | ||
10 | #[derive(Debug, Default, PartialEq, Eq)] | 13 | #[derive(Debug, Default, PartialEq, Eq)] |
11 | pub struct ItemScope { | 14 | pub struct ItemScope { |
@@ -30,7 +33,7 @@ pub struct ItemScope { | |||
30 | static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| { | 33 | static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| { |
31 | BuiltinType::ALL | 34 | BuiltinType::ALL |
32 | .iter() | 35 | .iter() |
33 | .map(|(name, ty)| (name.clone(), PerNs::types(ty.clone().into()))) | 36 | .map(|(name, ty)| (name.clone(), PerNs::types(ty.clone().into(), Visibility::Public))) |
34 | .collect() | 37 | .collect() |
35 | }); | 38 | }); |
36 | 39 | ||
@@ -144,8 +147,8 @@ impl ItemScope { | |||
144 | changed | 147 | changed |
145 | } | 148 | } |
146 | 149 | ||
147 | pub(crate) fn collect_resolutions(&self) -> Vec<(Name, PerNs)> { | 150 | pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a { |
148 | self.visible.iter().map(|(name, res)| (name.clone(), res.clone())).collect() | 151 | self.visible.iter().map(|(name, res)| (name.clone(), res.clone())) |
149 | } | 152 | } |
150 | 153 | ||
151 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { | 154 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { |
@@ -153,20 +156,20 @@ impl ItemScope { | |||
153 | } | 156 | } |
154 | } | 157 | } |
155 | 158 | ||
156 | impl From<ModuleDefId> for PerNs { | 159 | impl PerNs { |
157 | fn from(def: ModuleDefId) -> PerNs { | 160 | pub(crate) fn from_def(def: ModuleDefId, v: Visibility) -> PerNs { |
158 | match def { | 161 | match def { |
159 | ModuleDefId::ModuleId(_) => PerNs::types(def), | 162 | ModuleDefId::ModuleId(_) => PerNs::types(def, v), |
160 | ModuleDefId::FunctionId(_) => PerNs::values(def), | 163 | ModuleDefId::FunctionId(_) => PerNs::values(def, v), |
161 | ModuleDefId::AdtId(adt) => match adt { | 164 | ModuleDefId::AdtId(adt) => match adt { |
162 | AdtId::StructId(_) | AdtId::UnionId(_) => PerNs::both(def, def), | 165 | AdtId::StructId(_) | AdtId::UnionId(_) => PerNs::both(def, def, v), |
163 | AdtId::EnumId(_) => PerNs::types(def), | 166 | AdtId::EnumId(_) => PerNs::types(def, v), |
164 | }, | 167 | }, |
165 | ModuleDefId::EnumVariantId(_) => PerNs::both(def, def), | 168 | ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v), |
166 | ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def), | 169 | ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v), |
167 | ModuleDefId::TraitId(_) => PerNs::types(def), | 170 | ModuleDefId::TraitId(_) => PerNs::types(def, v), |
168 | ModuleDefId::TypeAliasId(_) => PerNs::types(def), | 171 | ModuleDefId::TypeAliasId(_) => PerNs::types(def, v), |
169 | ModuleDefId::BuiltinType(_) => PerNs::types(def), | 172 | ModuleDefId::BuiltinType(_) => PerNs::types(def, v), |
170 | } | 173 | } |
171 | } | 174 | } |
172 | } | 175 | } |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index f6c7f38d1..61f044ecf 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -36,6 +36,8 @@ pub mod nameres; | |||
36 | pub mod src; | 36 | pub mod src; |
37 | pub mod child_by_source; | 37 | pub mod child_by_source; |
38 | 38 | ||
39 | pub mod visibility; | ||
40 | |||
39 | #[cfg(test)] | 41 | #[cfg(test)] |
40 | mod test_db; | 42 | mod test_db; |
41 | #[cfg(test)] | 43 | #[cfg(test)] |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index b9f40d3dd..8a22b0585 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -24,6 +24,7 @@ use crate::{ | |||
24 | }, | 24 | }, |
25 | path::{ModPath, PathKind}, | 25 | path::{ModPath, PathKind}, |
26 | per_ns::PerNs, | 26 | per_ns::PerNs, |
27 | visibility::Visibility, | ||
27 | AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, | 28 | AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, |
28 | LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, | 29 | LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, |
29 | }; | 30 | }; |
@@ -108,7 +109,7 @@ struct MacroDirective { | |||
108 | struct DefCollector<'a, DB> { | 109 | struct DefCollector<'a, DB> { |
109 | db: &'a DB, | 110 | db: &'a DB, |
110 | def_map: CrateDefMap, | 111 | def_map: CrateDefMap, |
111 | glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, raw::Import)>>, | 112 | glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>, |
112 | unresolved_imports: Vec<ImportDirective>, | 113 | unresolved_imports: Vec<ImportDirective>, |
113 | resolved_imports: Vec<ImportDirective>, | 114 | resolved_imports: Vec<ImportDirective>, |
114 | unexpanded_macros: Vec<MacroDirective>, | 115 | unexpanded_macros: Vec<MacroDirective>, |
@@ -214,7 +215,11 @@ where | |||
214 | // In Rust, `#[macro_export]` macros are unconditionally visible at the | 215 | // In Rust, `#[macro_export]` macros are unconditionally visible at the |
215 | // crate root, even if the parent modules is **not** visible. | 216 | // crate root, even if the parent modules is **not** visible. |
216 | if export { | 217 | if export { |
217 | self.update(self.def_map.root, &[(name, PerNs::macros(macro_))]); | 218 | self.update( |
219 | self.def_map.root, | ||
220 | &[(name, PerNs::macros(macro_, Visibility::Public))], | ||
221 | Visibility::Public, | ||
222 | ); | ||
218 | } | 223 | } |
219 | } | 224 | } |
220 | 225 | ||
@@ -348,9 +353,12 @@ where | |||
348 | 353 | ||
349 | fn record_resolved_import(&mut self, directive: &ImportDirective) { | 354 | fn record_resolved_import(&mut self, directive: &ImportDirective) { |
350 | let module_id = directive.module_id; | 355 | let module_id = directive.module_id; |
351 | let import_id = directive.import_id; | ||
352 | let import = &directive.import; | 356 | let import = &directive.import; |
353 | let def = directive.status.namespaces(); | 357 | let def = directive.status.namespaces(); |
358 | let vis = self | ||
359 | .def_map | ||
360 | .resolve_visibility(self.db, module_id, &directive.import.visibility) | ||
361 | .unwrap_or(Visibility::Public); | ||
354 | 362 | ||
355 | if import.is_glob { | 363 | if import.is_glob { |
356 | log::debug!("glob import: {:?}", import); | 364 | log::debug!("glob import: {:?}", import); |
@@ -366,9 +374,16 @@ where | |||
366 | let scope = &item_map[m.local_id].scope; | 374 | let scope = &item_map[m.local_id].scope; |
367 | 375 | ||
368 | // Module scoped macros is included | 376 | // Module scoped macros is included |
369 | let items = scope.collect_resolutions(); | 377 | let items = scope |
370 | 378 | .resolutions() | |
371 | self.update(module_id, &items); | 379 | // only keep visible names... |
380 | .map(|(n, res)| { | ||
381 | (n, res.filter_visibility(|v| v.is_visible_from_other_crate())) | ||
382 | }) | ||
383 | .filter(|(_, res)| !res.is_none()) | ||
384 | .collect::<Vec<_>>(); | ||
385 | |||
386 | self.update(module_id, &items, vis); | ||
372 | } else { | 387 | } else { |
373 | // glob import from same crate => we do an initial | 388 | // glob import from same crate => we do an initial |
374 | // import, and then need to propagate any further | 389 | // import, and then need to propagate any further |
@@ -376,13 +391,25 @@ where | |||
376 | let scope = &self.def_map[m.local_id].scope; | 391 | let scope = &self.def_map[m.local_id].scope; |
377 | 392 | ||
378 | // Module scoped macros is included | 393 | // Module scoped macros is included |
379 | let items = scope.collect_resolutions(); | 394 | let items = scope |
380 | 395 | .resolutions() | |
381 | self.update(module_id, &items); | 396 | // only keep visible names... |
397 | .map(|(n, res)| { | ||
398 | ( | ||
399 | n, | ||
400 | res.filter_visibility(|v| { | ||
401 | v.is_visible_from_def_map(&self.def_map, module_id) | ||
402 | }), | ||
403 | ) | ||
404 | }) | ||
405 | .filter(|(_, res)| !res.is_none()) | ||
406 | .collect::<Vec<_>>(); | ||
407 | |||
408 | self.update(module_id, &items, vis); | ||
382 | // record the glob import in case we add further items | 409 | // record the glob import in case we add further items |
383 | let glob = self.glob_imports.entry(m.local_id).or_default(); | 410 | let glob = self.glob_imports.entry(m.local_id).or_default(); |
384 | if !glob.iter().any(|it| *it == (module_id, import_id)) { | 411 | if !glob.iter().any(|(mid, _)| *mid == module_id) { |
385 | glob.push((module_id, import_id)); | 412 | glob.push((module_id, vis)); |
386 | } | 413 | } |
387 | } | 414 | } |
388 | } | 415 | } |
@@ -396,11 +423,11 @@ where | |||
396 | .map(|(local_id, variant_data)| { | 423 | .map(|(local_id, variant_data)| { |
397 | let name = variant_data.name.clone(); | 424 | let name = variant_data.name.clone(); |
398 | let variant = EnumVariantId { parent: e, local_id }; | 425 | let variant = EnumVariantId { parent: e, local_id }; |
399 | let res = PerNs::both(variant.into(), variant.into()); | 426 | let res = PerNs::both(variant.into(), variant.into(), vis); |
400 | (name, res) | 427 | (name, res) |
401 | }) | 428 | }) |
402 | .collect::<Vec<_>>(); | 429 | .collect::<Vec<_>>(); |
403 | self.update(module_id, &resolutions); | 430 | self.update(module_id, &resolutions, vis); |
404 | } | 431 | } |
405 | Some(d) => { | 432 | Some(d) => { |
406 | log::debug!("glob import {:?} from non-module/enum {:?}", import, d); | 433 | log::debug!("glob import {:?} from non-module/enum {:?}", import, d); |
@@ -422,21 +449,24 @@ where | |||
422 | } | 449 | } |
423 | } | 450 | } |
424 | 451 | ||
425 | self.update(module_id, &[(name, def)]); | 452 | self.update(module_id, &[(name, def)], vis); |
426 | } | 453 | } |
427 | None => tested_by!(bogus_paths), | 454 | None => tested_by!(bogus_paths), |
428 | } | 455 | } |
429 | } | 456 | } |
430 | } | 457 | } |
431 | 458 | ||
432 | fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)]) { | 459 | fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)], vis: Visibility) { |
433 | self.update_recursive(module_id, resolutions, 0) | 460 | self.update_recursive(module_id, resolutions, vis, 0) |
434 | } | 461 | } |
435 | 462 | ||
436 | fn update_recursive( | 463 | fn update_recursive( |
437 | &mut self, | 464 | &mut self, |
438 | module_id: LocalModuleId, | 465 | module_id: LocalModuleId, |
439 | resolutions: &[(Name, PerNs)], | 466 | resolutions: &[(Name, PerNs)], |
467 | // All resolutions are imported with this visibility; the visibilies in | ||
468 | // the `PerNs` values are ignored and overwritten | ||
469 | vis: Visibility, | ||
440 | depth: usize, | 470 | depth: usize, |
441 | ) { | 471 | ) { |
442 | if depth > 100 { | 472 | if depth > 100 { |
@@ -446,7 +476,7 @@ where | |||
446 | let scope = &mut self.def_map.modules[module_id].scope; | 476 | let scope = &mut self.def_map.modules[module_id].scope; |
447 | let mut changed = false; | 477 | let mut changed = false; |
448 | for (name, res) in resolutions { | 478 | for (name, res) in resolutions { |
449 | changed |= scope.push_res(name.clone(), *res); | 479 | changed |= scope.push_res(name.clone(), res.with_visibility(vis)); |
450 | } | 480 | } |
451 | 481 | ||
452 | if !changed { | 482 | if !changed { |
@@ -459,9 +489,13 @@ where | |||
459 | .flat_map(|v| v.iter()) | 489 | .flat_map(|v| v.iter()) |
460 | .cloned() | 490 | .cloned() |
461 | .collect::<Vec<_>>(); | 491 | .collect::<Vec<_>>(); |
462 | for (glob_importing_module, _glob_import) in glob_imports { | 492 | for (glob_importing_module, glob_import_vis) in glob_imports { |
463 | // We pass the glob import so that the tracked import in those modules is that glob import | 493 | // we know all resolutions have the same visibility (`vis`), so we |
464 | self.update_recursive(glob_importing_module, resolutions, depth + 1); | 494 | // just need to check that once |
495 | if !vis.is_visible_from_def_map(&self.def_map, glob_importing_module) { | ||
496 | continue; | ||
497 | } | ||
498 | self.update_recursive(glob_importing_module, resolutions, glob_import_vis, depth + 1); | ||
465 | } | 499 | } |
466 | } | 500 | } |
467 | 501 | ||
@@ -633,9 +667,13 @@ where | |||
633 | let is_macro_use = attrs.by_key("macro_use").exists(); | 667 | let is_macro_use = attrs.by_key("macro_use").exists(); |
634 | match module { | 668 | match module { |
635 | // inline module, just recurse | 669 | // inline module, just recurse |
636 | raw::ModuleData::Definition { name, items, ast_id } => { | 670 | raw::ModuleData::Definition { name, visibility, items, ast_id } => { |
637 | let module_id = | 671 | let module_id = self.push_child_module( |
638 | self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None); | 672 | name.clone(), |
673 | AstId::new(self.file_id, *ast_id), | ||
674 | None, | ||
675 | &visibility, | ||
676 | ); | ||
639 | 677 | ||
640 | ModCollector { | 678 | ModCollector { |
641 | def_collector: &mut *self.def_collector, | 679 | def_collector: &mut *self.def_collector, |
@@ -650,7 +688,7 @@ where | |||
650 | } | 688 | } |
651 | } | 689 | } |
652 | // out of line module, resolve, parse and recurse | 690 | // out of line module, resolve, parse and recurse |
653 | raw::ModuleData::Declaration { name, ast_id } => { | 691 | raw::ModuleData::Declaration { name, visibility, ast_id } => { |
654 | let ast_id = AstId::new(self.file_id, *ast_id); | 692 | let ast_id = AstId::new(self.file_id, *ast_id); |
655 | match self.mod_dir.resolve_declaration( | 693 | match self.mod_dir.resolve_declaration( |
656 | self.def_collector.db, | 694 | self.def_collector.db, |
@@ -659,7 +697,12 @@ where | |||
659 | path_attr, | 697 | path_attr, |
660 | ) { | 698 | ) { |
661 | Ok((file_id, mod_dir)) => { | 699 | Ok((file_id, mod_dir)) => { |
662 | let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); | 700 | let module_id = self.push_child_module( |
701 | name.clone(), | ||
702 | ast_id, | ||
703 | Some(file_id), | ||
704 | &visibility, | ||
705 | ); | ||
663 | let raw_items = self.def_collector.db.raw_items(file_id.into()); | 706 | let raw_items = self.def_collector.db.raw_items(file_id.into()); |
664 | ModCollector { | 707 | ModCollector { |
665 | def_collector: &mut *self.def_collector, | 708 | def_collector: &mut *self.def_collector, |
@@ -690,7 +733,13 @@ where | |||
690 | name: Name, | 733 | name: Name, |
691 | declaration: AstId<ast::Module>, | 734 | declaration: AstId<ast::Module>, |
692 | definition: Option<FileId>, | 735 | definition: Option<FileId>, |
736 | visibility: &crate::visibility::RawVisibility, | ||
693 | ) -> LocalModuleId { | 737 | ) -> LocalModuleId { |
738 | let vis = self | ||
739 | .def_collector | ||
740 | .def_map | ||
741 | .resolve_visibility(self.def_collector.db, self.module_id, visibility) | ||
742 | .unwrap_or(Visibility::Public); | ||
694 | let modules = &mut self.def_collector.def_map.modules; | 743 | let modules = &mut self.def_collector.def_map.modules; |
695 | let res = modules.alloc(ModuleData::default()); | 744 | let res = modules.alloc(ModuleData::default()); |
696 | modules[res].parent = Some(self.module_id); | 745 | modules[res].parent = Some(self.module_id); |
@@ -702,7 +751,7 @@ where | |||
702 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; | 751 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; |
703 | let def: ModuleDefId = module.into(); | 752 | let def: ModuleDefId = module.into(); |
704 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 753 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
705 | self.def_collector.update(self.module_id, &[(name, def.into())]); | 754 | self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis); |
706 | res | 755 | res |
707 | } | 756 | } |
708 | 757 | ||
@@ -716,6 +765,7 @@ where | |||
716 | 765 | ||
717 | let name = def.name.clone(); | 766 | let name = def.name.clone(); |
718 | let container = ContainerId::ModuleId(module); | 767 | let container = ContainerId::ModuleId(module); |
768 | let vis = &def.visibility; | ||
719 | let def: ModuleDefId = match def.kind { | 769 | let def: ModuleDefId = match def.kind { |
720 | raw::DefKind::Function(ast_id) => FunctionLoc { | 770 | raw::DefKind::Function(ast_id) => FunctionLoc { |
721 | container: container.into(), | 771 | container: container.into(), |
@@ -761,7 +811,12 @@ where | |||
761 | .into(), | 811 | .into(), |
762 | }; | 812 | }; |
763 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 813 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
764 | self.def_collector.update(self.module_id, &[(name, def.into())]) | 814 | let vis = self |
815 | .def_collector | ||
816 | .def_map | ||
817 | .resolve_visibility(self.def_collector.db, self.module_id, vis) | ||
818 | .unwrap_or(Visibility::Public); | ||
819 | self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis) | ||
765 | } | 820 | } |
766 | 821 | ||
767 | fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { | 822 | fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { |
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 695014c7b..fd6422d60 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs | |||
@@ -21,6 +21,7 @@ use crate::{ | |||
21 | nameres::{BuiltinShadowMode, CrateDefMap}, | 21 | nameres::{BuiltinShadowMode, CrateDefMap}, |
22 | path::{ModPath, PathKind}, | 22 | path::{ModPath, PathKind}, |
23 | per_ns::PerNs, | 23 | per_ns::PerNs, |
24 | visibility::{RawVisibility, Visibility}, | ||
24 | AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, | 25 | AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, |
25 | }; | 26 | }; |
26 | 27 | ||
@@ -61,7 +62,35 @@ impl ResolvePathResult { | |||
61 | 62 | ||
62 | impl CrateDefMap { | 63 | impl CrateDefMap { |
63 | pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { | 64 | pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { |
64 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)) | 65 | self.extern_prelude |
66 | .get(name) | ||
67 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) | ||
68 | } | ||
69 | |||
70 | pub(crate) fn resolve_visibility( | ||
71 | &self, | ||
72 | db: &impl DefDatabase, | ||
73 | original_module: LocalModuleId, | ||
74 | visibility: &RawVisibility, | ||
75 | ) -> Option<Visibility> { | ||
76 | match visibility { | ||
77 | RawVisibility::Module(path) => { | ||
78 | let (result, remaining) = | ||
79 | self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); | ||
80 | if remaining.is_some() { | ||
81 | return None; | ||
82 | } | ||
83 | let types = result.take_types()?; | ||
84 | match types { | ||
85 | ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)), | ||
86 | _ => { | ||
87 | // error: visibility needs to refer to module | ||
88 | None | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | RawVisibility::Public => Some(Visibility::Public), | ||
93 | } | ||
65 | } | 94 | } |
66 | 95 | ||
67 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change | 96 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change |
@@ -88,17 +117,21 @@ impl CrateDefMap { | |||
88 | PathKind::DollarCrate(krate) => { | 117 | PathKind::DollarCrate(krate) => { |
89 | if krate == self.krate { | 118 | if krate == self.krate { |
90 | tested_by!(macro_dollar_crate_self); | 119 | tested_by!(macro_dollar_crate_self); |
91 | PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into()) | 120 | PerNs::types( |
121 | ModuleId { krate: self.krate, local_id: self.root }.into(), | ||
122 | Visibility::Public, | ||
123 | ) | ||
92 | } else { | 124 | } else { |
93 | let def_map = db.crate_def_map(krate); | 125 | let def_map = db.crate_def_map(krate); |
94 | let module = ModuleId { krate, local_id: def_map.root }; | 126 | let module = ModuleId { krate, local_id: def_map.root }; |
95 | tested_by!(macro_dollar_crate_other); | 127 | tested_by!(macro_dollar_crate_other); |
96 | PerNs::types(module.into()) | 128 | PerNs::types(module.into(), Visibility::Public) |
97 | } | 129 | } |
98 | } | 130 | } |
99 | PathKind::Crate => { | 131 | PathKind::Crate => PerNs::types( |
100 | PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into()) | 132 | ModuleId { krate: self.krate, local_id: self.root }.into(), |
101 | } | 133 | Visibility::Public, |
134 | ), | ||
102 | // plain import or absolute path in 2015: crate-relative with | 135 | // plain import or absolute path in 2015: crate-relative with |
103 | // fallback to extern prelude (with the simplification in | 136 | // fallback to extern prelude (with the simplification in |
104 | // rust-lang/rust#57745) | 137 | // rust-lang/rust#57745) |
@@ -126,7 +159,10 @@ impl CrateDefMap { | |||
126 | let m = successors(Some(original_module), |m| self.modules[*m].parent) | 159 | let m = successors(Some(original_module), |m| self.modules[*m].parent) |
127 | .nth(lvl as usize); | 160 | .nth(lvl as usize); |
128 | if let Some(local_id) = m { | 161 | if let Some(local_id) = m { |
129 | PerNs::types(ModuleId { krate: self.krate, local_id }.into()) | 162 | PerNs::types( |
163 | ModuleId { krate: self.krate, local_id }.into(), | ||
164 | Visibility::Public, | ||
165 | ) | ||
130 | } else { | 166 | } else { |
131 | log::debug!("super path in root module"); | 167 | log::debug!("super path in root module"); |
132 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); | 168 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); |
@@ -140,7 +176,7 @@ impl CrateDefMap { | |||
140 | }; | 176 | }; |
141 | if let Some(def) = self.extern_prelude.get(&segment) { | 177 | if let Some(def) = self.extern_prelude.get(&segment) { |
142 | log::debug!("absolute path {:?} resolved to crate {:?}", path, def); | 178 | log::debug!("absolute path {:?} resolved to crate {:?}", path, def); |
143 | PerNs::types(*def) | 179 | PerNs::types(*def, Visibility::Public) |
144 | } else { | 180 | } else { |
145 | return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude | 181 | return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude |
146 | } | 182 | } |
@@ -148,7 +184,7 @@ impl CrateDefMap { | |||
148 | }; | 184 | }; |
149 | 185 | ||
150 | for (i, segment) in segments { | 186 | for (i, segment) in segments { |
151 | let curr = match curr_per_ns.take_types() { | 187 | let (curr, vis) = match curr_per_ns.take_types_vis() { |
152 | Some(r) => r, | 188 | Some(r) => r, |
153 | None => { | 189 | None => { |
154 | // we still have path segments left, but the path so far | 190 | // we still have path segments left, but the path so far |
@@ -189,11 +225,11 @@ impl CrateDefMap { | |||
189 | match enum_data.variant(&segment) { | 225 | match enum_data.variant(&segment) { |
190 | Some(local_id) => { | 226 | Some(local_id) => { |
191 | let variant = EnumVariantId { parent: e, local_id }; | 227 | let variant = EnumVariantId { parent: e, local_id }; |
192 | PerNs::both(variant.into(), variant.into()) | 228 | PerNs::both(variant.into(), variant.into(), Visibility::Public) |
193 | } | 229 | } |
194 | None => { | 230 | None => { |
195 | return ResolvePathResult::with( | 231 | return ResolvePathResult::with( |
196 | PerNs::types(e.into()), | 232 | PerNs::types(e.into(), vis), |
197 | ReachedFixedPoint::Yes, | 233 | ReachedFixedPoint::Yes, |
198 | Some(i), | 234 | Some(i), |
199 | Some(self.krate), | 235 | Some(self.krate), |
@@ -211,7 +247,7 @@ impl CrateDefMap { | |||
211 | ); | 247 | ); |
212 | 248 | ||
213 | return ResolvePathResult::with( | 249 | return ResolvePathResult::with( |
214 | PerNs::types(s), | 250 | PerNs::types(s, vis), |
215 | ReachedFixedPoint::Yes, | 251 | ReachedFixedPoint::Yes, |
216 | Some(i), | 252 | Some(i), |
217 | Some(self.krate), | 253 | Some(self.krate), |
@@ -235,11 +271,15 @@ impl CrateDefMap { | |||
235 | // - current module / scope | 271 | // - current module / scope |
236 | // - extern prelude | 272 | // - extern prelude |
237 | // - std prelude | 273 | // - std prelude |
238 | let from_legacy_macro = | 274 | let from_legacy_macro = self[module] |
239 | self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); | 275 | .scope |
276 | .get_legacy_macro(name) | ||
277 | .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public)); | ||
240 | let from_scope = self[module].scope.get(name, shadow); | 278 | let from_scope = self[module].scope.get(name, shadow); |
241 | let from_extern_prelude = | 279 | let from_extern_prelude = self |
242 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); | 280 | .extern_prelude |
281 | .get(name) | ||
282 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)); | ||
243 | let from_prelude = self.resolve_in_prelude(db, name, shadow); | 283 | let from_prelude = self.resolve_in_prelude(db, name, shadow); |
244 | 284 | ||
245 | from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude) | 285 | from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude) |
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 73dc08745..fac1169ef 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs | |||
@@ -16,12 +16,15 @@ use hir_expand::{ | |||
16 | use ra_arena::{impl_arena_id, Arena, RawId}; | 16 | use ra_arena::{impl_arena_id, Arena, RawId}; |
17 | use ra_prof::profile; | 17 | use ra_prof::profile; |
18 | use ra_syntax::{ | 18 | use ra_syntax::{ |
19 | ast::{self, AttrsOwner, NameOwner}, | 19 | ast::{self, AttrsOwner, NameOwner, VisibilityOwner}, |
20 | AstNode, | 20 | AstNode, |
21 | }; | 21 | }; |
22 | use test_utils::tested_by; | 22 | use test_utils::tested_by; |
23 | 23 | ||
24 | use crate::{attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile}; | 24 | use crate::{ |
25 | attr::Attrs, db::DefDatabase, path::ModPath, visibility::RawVisibility, FileAstId, HirFileId, | ||
26 | InFile, | ||
27 | }; | ||
25 | 28 | ||
26 | /// `RawItems` is a set of top-level items in a file (except for impls). | 29 | /// `RawItems` is a set of top-level items in a file (except for impls). |
27 | /// | 30 | /// |
@@ -122,8 +125,17 @@ impl_arena_id!(Module); | |||
122 | 125 | ||
123 | #[derive(Debug, PartialEq, Eq)] | 126 | #[derive(Debug, PartialEq, Eq)] |
124 | pub(super) enum ModuleData { | 127 | pub(super) enum ModuleData { |
125 | Declaration { name: Name, ast_id: FileAstId<ast::Module> }, | 128 | Declaration { |
126 | Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> }, | 129 | name: Name, |
130 | visibility: RawVisibility, | ||
131 | ast_id: FileAstId<ast::Module>, | ||
132 | }, | ||
133 | Definition { | ||
134 | name: Name, | ||
135 | visibility: RawVisibility, | ||
136 | ast_id: FileAstId<ast::Module>, | ||
137 | items: Vec<RawItem>, | ||
138 | }, | ||
127 | } | 139 | } |
128 | 140 | ||
129 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 141 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -138,6 +150,7 @@ pub struct ImportData { | |||
138 | pub(super) is_prelude: bool, | 150 | pub(super) is_prelude: bool, |
139 | pub(super) is_extern_crate: bool, | 151 | pub(super) is_extern_crate: bool, |
140 | pub(super) is_macro_use: bool, | 152 | pub(super) is_macro_use: bool, |
153 | pub(super) visibility: RawVisibility, | ||
141 | } | 154 | } |
142 | 155 | ||
143 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 156 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -148,6 +161,7 @@ impl_arena_id!(Def); | |||
148 | pub(super) struct DefData { | 161 | pub(super) struct DefData { |
149 | pub(super) name: Name, | 162 | pub(super) name: Name, |
150 | pub(super) kind: DefKind, | 163 | pub(super) kind: DefKind, |
164 | pub(super) visibility: RawVisibility, | ||
151 | } | 165 | } |
152 | 166 | ||
153 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | 167 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] |
@@ -218,6 +232,7 @@ impl RawItemsCollector { | |||
218 | 232 | ||
219 | fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) { | 233 | fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) { |
220 | let attrs = self.parse_attrs(&item); | 234 | let attrs = self.parse_attrs(&item); |
235 | let visibility = RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene); | ||
221 | let (kind, name) = match item { | 236 | let (kind, name) = match item { |
222 | ast::ModuleItem::Module(module) => { | 237 | ast::ModuleItem::Module(module) => { |
223 | self.add_module(current_module, module); | 238 | self.add_module(current_module, module); |
@@ -266,7 +281,7 @@ impl RawItemsCollector { | |||
266 | }; | 281 | }; |
267 | if let Some(name) = name { | 282 | if let Some(name) = name { |
268 | let name = name.as_name(); | 283 | let name = name.as_name(); |
269 | let def = self.raw_items.defs.alloc(DefData { name, kind }); | 284 | let def = self.raw_items.defs.alloc(DefData { name, kind, visibility }); |
270 | self.push_item(current_module, attrs, RawItemKind::Def(def)); | 285 | self.push_item(current_module, attrs, RawItemKind::Def(def)); |
271 | } | 286 | } |
272 | } | 287 | } |
@@ -277,10 +292,12 @@ impl RawItemsCollector { | |||
277 | None => return, | 292 | None => return, |
278 | }; | 293 | }; |
279 | let attrs = self.parse_attrs(&module); | 294 | let attrs = self.parse_attrs(&module); |
295 | let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene); | ||
280 | 296 | ||
281 | let ast_id = self.source_ast_id_map.ast_id(&module); | 297 | let ast_id = self.source_ast_id_map.ast_id(&module); |
282 | if module.has_semi() { | 298 | if module.has_semi() { |
283 | let item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id }); | 299 | let item = |
300 | self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id }); | ||
284 | self.push_item(current_module, attrs, RawItemKind::Module(item)); | 301 | self.push_item(current_module, attrs, RawItemKind::Module(item)); |
285 | return; | 302 | return; |
286 | } | 303 | } |
@@ -288,6 +305,7 @@ impl RawItemsCollector { | |||
288 | if let Some(item_list) = module.item_list() { | 305 | if let Some(item_list) = module.item_list() { |
289 | let item = self.raw_items.modules.alloc(ModuleData::Definition { | 306 | let item = self.raw_items.modules.alloc(ModuleData::Definition { |
290 | name, | 307 | name, |
308 | visibility, | ||
291 | ast_id, | 309 | ast_id, |
292 | items: Vec::new(), | 310 | items: Vec::new(), |
293 | }); | 311 | }); |
@@ -302,6 +320,7 @@ impl RawItemsCollector { | |||
302 | // FIXME: cfg_attr | 320 | // FIXME: cfg_attr |
303 | let is_prelude = use_item.has_atom_attr("prelude_import"); | 321 | let is_prelude = use_item.has_atom_attr("prelude_import"); |
304 | let attrs = self.parse_attrs(&use_item); | 322 | let attrs = self.parse_attrs(&use_item); |
323 | let visibility = RawVisibility::from_ast_with_hygiene(use_item.visibility(), &self.hygiene); | ||
305 | 324 | ||
306 | let mut buf = Vec::new(); | 325 | let mut buf = Vec::new(); |
307 | ModPath::expand_use_item( | 326 | ModPath::expand_use_item( |
@@ -315,6 +334,7 @@ impl RawItemsCollector { | |||
315 | is_prelude, | 334 | is_prelude, |
316 | is_extern_crate: false, | 335 | is_extern_crate: false, |
317 | is_macro_use: false, | 336 | is_macro_use: false, |
337 | visibility: visibility.clone(), | ||
318 | }; | 338 | }; |
319 | buf.push(import_data); | 339 | buf.push(import_data); |
320 | }, | 340 | }, |
@@ -331,6 +351,8 @@ impl RawItemsCollector { | |||
331 | ) { | 351 | ) { |
332 | if let Some(name_ref) = extern_crate.name_ref() { | 352 | if let Some(name_ref) = extern_crate.name_ref() { |
333 | let path = ModPath::from_name_ref(&name_ref); | 353 | let path = ModPath::from_name_ref(&name_ref); |
354 | let visibility = | ||
355 | RawVisibility::from_ast_with_hygiene(extern_crate.visibility(), &self.hygiene); | ||
334 | let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); | 356 | let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); |
335 | let attrs = self.parse_attrs(&extern_crate); | 357 | let attrs = self.parse_attrs(&extern_crate); |
336 | // FIXME: cfg_attr | 358 | // FIXME: cfg_attr |
@@ -342,6 +364,7 @@ impl RawItemsCollector { | |||
342 | is_prelude: false, | 364 | is_prelude: false, |
343 | is_extern_crate: true, | 365 | is_extern_crate: true, |
344 | is_macro_use, | 366 | is_macro_use, |
367 | visibility, | ||
345 | }; | 368 | }; |
346 | self.push_import(current_module, attrs, import_data); | 369 | self.push_import(current_module, attrs, import_data); |
347 | } | 370 | } |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index ff474b53b..78bcdc850 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -12,8 +12,8 @@ use test_utils::covers; | |||
12 | 12 | ||
13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId}; | 13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId}; |
14 | 14 | ||
15 | fn def_map(fixtute: &str) -> String { | 15 | fn def_map(fixture: &str) -> String { |
16 | let dm = compute_crate_def_map(fixtute); | 16 | let dm = compute_crate_def_map(fixture); |
17 | render_crate_def_map(&dm) | 17 | render_crate_def_map(&dm) |
18 | } | 18 | } |
19 | 19 | ||
@@ -32,7 +32,7 @@ fn render_crate_def_map(map: &CrateDefMap) -> String { | |||
32 | *buf += path; | 32 | *buf += path; |
33 | *buf += "\n"; | 33 | *buf += "\n"; |
34 | 34 | ||
35 | let mut entries = map.modules[module].scope.collect_resolutions(); | 35 | let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect(); |
36 | entries.sort_by_key(|(name, _)| name.clone()); | 36 | entries.sort_by_key(|(name, _)| name.clone()); |
37 | 37 | ||
38 | for (name, def) in entries { | 38 | for (name, def) in entries { |
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs index 5e24cb94d..71fa0abe8 100644 --- a/crates/ra_hir_def/src/nameres/tests/globs.rs +++ b/crates/ra_hir_def/src/nameres/tests/globs.rs | |||
@@ -74,6 +74,83 @@ fn glob_2() { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | #[test] | 76 | #[test] |
77 | fn glob_privacy_1() { | ||
78 | let map = def_map( | ||
79 | " | ||
80 | //- /lib.rs | ||
81 | mod foo; | ||
82 | use foo::*; | ||
83 | |||
84 | //- /foo/mod.rs | ||
85 | pub mod bar; | ||
86 | pub use self::bar::*; | ||
87 | struct PrivateStructFoo; | ||
88 | |||
89 | //- /foo/bar.rs | ||
90 | pub struct Baz; | ||
91 | struct PrivateStructBar; | ||
92 | pub use super::*; | ||
93 | ", | ||
94 | ); | ||
95 | assert_snapshot!(map, @r###" | ||
96 | crate | ||
97 | Baz: t v | ||
98 | bar: t | ||
99 | foo: t | ||
100 | |||
101 | crate::foo | ||
102 | Baz: t v | ||
103 | PrivateStructFoo: t v | ||
104 | bar: t | ||
105 | |||
106 | crate::foo::bar | ||
107 | Baz: t v | ||
108 | PrivateStructBar: t v | ||
109 | PrivateStructFoo: t v | ||
110 | bar: t | ||
111 | "### | ||
112 | ); | ||
113 | } | ||
114 | |||
115 | #[test] | ||
116 | fn glob_privacy_2() { | ||
117 | let map = def_map( | ||
118 | " | ||
119 | //- /lib.rs | ||
120 | mod foo; | ||
121 | use foo::*; | ||
122 | use foo::bar::*; | ||
123 | |||
124 | //- /foo/mod.rs | ||
125 | mod bar; | ||
126 | fn Foo() {}; | ||
127 | pub struct Foo {}; | ||
128 | |||
129 | //- /foo/bar.rs | ||
130 | pub(super) struct PrivateBaz; | ||
131 | struct PrivateBar; | ||
132 | pub(crate) struct PubCrateStruct; | ||
133 | ", | ||
134 | ); | ||
135 | assert_snapshot!(map, @r###" | ||
136 | crate | ||
137 | Foo: t | ||
138 | PubCrateStruct: t v | ||
139 | foo: t | ||
140 | |||
141 | crate::foo | ||
142 | Foo: t v | ||
143 | bar: t | ||
144 | |||
145 | crate::foo::bar | ||
146 | PrivateBar: t v | ||
147 | PrivateBaz: t v | ||
148 | PubCrateStruct: t v | ||
149 | "### | ||
150 | ); | ||
151 | } | ||
152 | |||
153 | #[test] | ||
77 | fn glob_across_crates() { | 154 | fn glob_across_crates() { |
78 | covers!(glob_across_crates); | 155 | covers!(glob_across_crates); |
79 | let map = def_map( | 156 | let map = def_map( |
@@ -93,6 +170,26 @@ fn glob_across_crates() { | |||
93 | } | 170 | } |
94 | 171 | ||
95 | #[test] | 172 | #[test] |
173 | fn glob_privacy_across_crates() { | ||
174 | covers!(glob_across_crates); | ||
175 | let map = def_map( | ||
176 | " | ||
177 | //- /main.rs crate:main deps:test_crate | ||
178 | use test_crate::*; | ||
179 | |||
180 | //- /lib.rs crate:test_crate | ||
181 | pub struct Baz; | ||
182 | struct Foo; | ||
183 | ", | ||
184 | ); | ||
185 | assert_snapshot!(map, @r###" | ||
186 | ⋮crate | ||
187 | ⋮Baz: t v | ||
188 | "### | ||
189 | ); | ||
190 | } | ||
191 | |||
192 | #[test] | ||
96 | fn glob_enum() { | 193 | fn glob_enum() { |
97 | covers!(glob_enum); | 194 | covers!(glob_enum); |
98 | let map = def_map( | 195 | let map = def_map( |
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs index ef2e9435c..faeb7aa4d 100644 --- a/crates/ra_hir_def/src/nameres/tests/incremental.rs +++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs | |||
@@ -116,7 +116,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
116 | let events = db.log_executed(|| { | 116 | let events = db.log_executed(|| { |
117 | let crate_def_map = db.crate_def_map(krate); | 117 | let crate_def_map = db.crate_def_map(krate); |
118 | let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); | 118 | let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); |
119 | assert_eq!(module_data.scope.collect_resolutions().len(), 1); | 119 | assert_eq!(module_data.scope.resolutions().collect::<Vec<_>>().len(), 1); |
120 | }); | 120 | }); |
121 | assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) | 121 | assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) |
122 | } | 122 | } |
@@ -126,7 +126,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
126 | let events = db.log_executed(|| { | 126 | let events = db.log_executed(|| { |
127 | let crate_def_map = db.crate_def_map(krate); | 127 | let crate_def_map = db.crate_def_map(krate); |
128 | let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); | 128 | let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); |
129 | assert_eq!(module_data.scope.collect_resolutions().len(), 1); | 129 | assert_eq!(module_data.scope.resolutions().collect::<Vec<_>>().len(), 1); |
130 | }); | 130 | }); |
131 | assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) | 131 | assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) |
132 | } | 132 | } |
diff --git a/crates/ra_hir_def/src/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs index 3a5105028..6e435c8c1 100644 --- a/crates/ra_hir_def/src/per_ns.rs +++ b/crates/ra_hir_def/src/per_ns.rs | |||
@@ -5,13 +5,13 @@ | |||
5 | 5 | ||
6 | use hir_expand::MacroDefId; | 6 | use hir_expand::MacroDefId; |
7 | 7 | ||
8 | use crate::ModuleDefId; | 8 | use crate::{visibility::Visibility, ModuleDefId}; |
9 | 9 | ||
10 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 10 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
11 | pub struct PerNs { | 11 | pub struct PerNs { |
12 | pub types: Option<ModuleDefId>, | 12 | pub types: Option<(ModuleDefId, Visibility)>, |
13 | pub values: Option<ModuleDefId>, | 13 | pub values: Option<(ModuleDefId, Visibility)>, |
14 | pub macros: Option<MacroDefId>, | 14 | pub macros: Option<(MacroDefId, Visibility)>, |
15 | } | 15 | } |
16 | 16 | ||
17 | impl Default for PerNs { | 17 | impl Default for PerNs { |
@@ -25,20 +25,20 @@ impl PerNs { | |||
25 | PerNs { types: None, values: None, macros: None } | 25 | PerNs { types: None, values: None, macros: None } |
26 | } | 26 | } |
27 | 27 | ||
28 | pub fn values(t: ModuleDefId) -> PerNs { | 28 | pub fn values(t: ModuleDefId, v: Visibility) -> PerNs { |
29 | PerNs { types: None, values: Some(t), macros: None } | 29 | PerNs { types: None, values: Some((t, v)), macros: None } |
30 | } | 30 | } |
31 | 31 | ||
32 | pub fn types(t: ModuleDefId) -> PerNs { | 32 | pub fn types(t: ModuleDefId, v: Visibility) -> PerNs { |
33 | PerNs { types: Some(t), values: None, macros: None } | 33 | PerNs { types: Some((t, v)), values: None, macros: None } |
34 | } | 34 | } |
35 | 35 | ||
36 | pub fn both(types: ModuleDefId, values: ModuleDefId) -> PerNs { | 36 | pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs { |
37 | PerNs { types: Some(types), values: Some(values), macros: None } | 37 | PerNs { types: Some((types, v)), values: Some((values, v)), macros: None } |
38 | } | 38 | } |
39 | 39 | ||
40 | pub fn macros(macro_: MacroDefId) -> PerNs { | 40 | pub fn macros(macro_: MacroDefId, v: Visibility) -> PerNs { |
41 | PerNs { types: None, values: None, macros: Some(macro_) } | 41 | PerNs { types: None, values: None, macros: Some((macro_, v)) } |
42 | } | 42 | } |
43 | 43 | ||
44 | pub fn is_none(&self) -> bool { | 44 | pub fn is_none(&self) -> bool { |
@@ -46,15 +46,35 @@ impl PerNs { | |||
46 | } | 46 | } |
47 | 47 | ||
48 | pub fn take_types(self) -> Option<ModuleDefId> { | 48 | pub fn take_types(self) -> Option<ModuleDefId> { |
49 | self.types.map(|it| it.0) | ||
50 | } | ||
51 | |||
52 | pub fn take_types_vis(self) -> Option<(ModuleDefId, Visibility)> { | ||
49 | self.types | 53 | self.types |
50 | } | 54 | } |
51 | 55 | ||
52 | pub fn take_values(self) -> Option<ModuleDefId> { | 56 | pub fn take_values(self) -> Option<ModuleDefId> { |
53 | self.values | 57 | self.values.map(|it| it.0) |
54 | } | 58 | } |
55 | 59 | ||
56 | pub fn take_macros(self) -> Option<MacroDefId> { | 60 | pub fn take_macros(self) -> Option<MacroDefId> { |
57 | self.macros | 61 | self.macros.map(|it| it.0) |
62 | } | ||
63 | |||
64 | pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { | ||
65 | PerNs { | ||
66 | types: self.types.filter(|(_, v)| f(*v)), | ||
67 | values: self.values.filter(|(_, v)| f(*v)), | ||
68 | macros: self.macros.filter(|(_, v)| f(*v)), | ||
69 | } | ||
70 | } | ||
71 | |||
72 | pub fn with_visibility(self, vis: Visibility) -> PerNs { | ||
73 | PerNs { | ||
74 | types: self.types.map(|(it, _)| (it, vis)), | ||
75 | values: self.values.map(|(it, _)| (it, vis)), | ||
76 | macros: self.macros.map(|(it, _)| (it, vis)), | ||
77 | } | ||
58 | } | 78 | } |
59 | 79 | ||
60 | pub fn or(self, other: PerNs) -> PerNs { | 80 | pub fn or(self, other: PerNs) -> PerNs { |
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index cf3c33d78..43dc751d9 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -19,6 +19,7 @@ use crate::{ | |||
19 | nameres::CrateDefMap, | 19 | nameres::CrateDefMap, |
20 | path::{ModPath, PathKind}, | 20 | path::{ModPath, PathKind}, |
21 | per_ns::PerNs, | 21 | per_ns::PerNs, |
22 | visibility::{RawVisibility, Visibility}, | ||
22 | AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, | 23 | AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, |
23 | FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, | 24 | FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, |
24 | StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, | 25 | StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, |
@@ -231,6 +232,23 @@ impl Resolver { | |||
231 | Some(res) | 232 | Some(res) |
232 | } | 233 | } |
233 | 234 | ||
235 | pub fn resolve_visibility( | ||
236 | &self, | ||
237 | db: &impl DefDatabase, | ||
238 | visibility: &RawVisibility, | ||
239 | ) -> Option<Visibility> { | ||
240 | match visibility { | ||
241 | RawVisibility::Module(_) => { | ||
242 | let (item_map, module) = match self.module() { | ||
243 | Some(it) => it, | ||
244 | None => return None, | ||
245 | }; | ||
246 | item_map.resolve_visibility(db, module, visibility) | ||
247 | } | ||
248 | RawVisibility::Public => Some(Visibility::Public), | ||
249 | } | ||
250 | } | ||
251 | |||
234 | pub fn resolve_path_in_value_ns( | 252 | pub fn resolve_path_in_value_ns( |
235 | &self, | 253 | &self, |
236 | db: &impl DefDatabase, | 254 | db: &impl DefDatabase, |
@@ -448,10 +466,10 @@ impl Scope { | |||
448 | f(name.clone(), ScopeDef::PerNs(def)); | 466 | f(name.clone(), ScopeDef::PerNs(def)); |
449 | }); | 467 | }); |
450 | m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { | 468 | m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { |
451 | f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_))); | 469 | f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_, Visibility::Public))); |
452 | }); | 470 | }); |
453 | m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| { | 471 | m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| { |
454 | f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into()))); | 472 | f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into(), Visibility::Public))); |
455 | }); | 473 | }); |
456 | if let Some(prelude) = m.crate_def_map.prelude { | 474 | if let Some(prelude) = m.crate_def_map.prelude { |
457 | let prelude_def_map = db.crate_def_map(prelude.krate); | 475 | let prelude_def_map = db.crate_def_map(prelude.krate); |
diff --git a/crates/ra_hir_def/src/visibility.rs b/crates/ra_hir_def/src/visibility.rs new file mode 100644 index 000000000..d8296da4b --- /dev/null +++ b/crates/ra_hir_def/src/visibility.rs | |||
@@ -0,0 +1,120 @@ | |||
1 | //! Defines hir-level representation of visibility (e.g. `pub` and `pub(crate)`). | ||
2 | |||
3 | use hir_expand::{hygiene::Hygiene, InFile}; | ||
4 | use ra_syntax::ast; | ||
5 | |||
6 | use crate::{ | ||
7 | db::DefDatabase, | ||
8 | path::{ModPath, PathKind}, | ||
9 | ModuleId, | ||
10 | }; | ||
11 | |||
12 | /// Visibility of an item, not yet resolved. | ||
13 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
14 | pub enum RawVisibility { | ||
15 | /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is | ||
16 | /// equivalent to `pub(self)`. | ||
17 | Module(ModPath), | ||
18 | /// `pub`. | ||
19 | Public, | ||
20 | } | ||
21 | |||
22 | impl RawVisibility { | ||
23 | const fn private() -> RawVisibility { | ||
24 | let path = ModPath { kind: PathKind::Super(0), segments: Vec::new() }; | ||
25 | RawVisibility::Module(path) | ||
26 | } | ||
27 | |||
28 | pub(crate) fn from_ast( | ||
29 | db: &impl DefDatabase, | ||
30 | node: InFile<Option<ast::Visibility>>, | ||
31 | ) -> RawVisibility { | ||
32 | Self::from_ast_with_hygiene(node.value, &Hygiene::new(db, node.file_id)) | ||
33 | } | ||
34 | |||
35 | pub(crate) fn from_ast_with_hygiene( | ||
36 | node: Option<ast::Visibility>, | ||
37 | hygiene: &Hygiene, | ||
38 | ) -> RawVisibility { | ||
39 | let node = match node { | ||
40 | None => return RawVisibility::private(), | ||
41 | Some(node) => node, | ||
42 | }; | ||
43 | match node.kind() { | ||
44 | ast::VisibilityKind::In(path) => { | ||
45 | let path = ModPath::from_src(path, hygiene); | ||
46 | let path = match path { | ||
47 | None => return RawVisibility::private(), | ||
48 | Some(path) => path, | ||
49 | }; | ||
50 | RawVisibility::Module(path) | ||
51 | } | ||
52 | ast::VisibilityKind::PubCrate => { | ||
53 | let path = ModPath { kind: PathKind::Crate, segments: Vec::new() }; | ||
54 | RawVisibility::Module(path) | ||
55 | } | ||
56 | ast::VisibilityKind::PubSuper => { | ||
57 | let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() }; | ||
58 | RawVisibility::Module(path) | ||
59 | } | ||
60 | ast::VisibilityKind::Pub => RawVisibility::Public, | ||
61 | } | ||
62 | } | ||
63 | |||
64 | pub fn resolve( | ||
65 | &self, | ||
66 | db: &impl DefDatabase, | ||
67 | resolver: &crate::resolver::Resolver, | ||
68 | ) -> Visibility { | ||
69 | // we fall back to public visibility (i.e. fail open) if the path can't be resolved | ||
70 | resolver.resolve_visibility(db, self).unwrap_or(Visibility::Public) | ||
71 | } | ||
72 | } | ||
73 | |||
74 | /// Visibility of an item, with the path resolved. | ||
75 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||
76 | pub enum Visibility { | ||
77 | /// Visibility is restricted to a certain module. | ||
78 | Module(ModuleId), | ||
79 | /// Visibility is unrestricted. | ||
80 | Public, | ||
81 | } | ||
82 | |||
83 | impl Visibility { | ||
84 | pub fn is_visible_from(self, db: &impl DefDatabase, from_module: ModuleId) -> bool { | ||
85 | let to_module = match self { | ||
86 | Visibility::Module(m) => m, | ||
87 | Visibility::Public => return true, | ||
88 | }; | ||
89 | // if they're not in the same crate, it can't be visible | ||
90 | if from_module.krate != to_module.krate { | ||
91 | return false; | ||
92 | } | ||
93 | let def_map = db.crate_def_map(from_module.krate); | ||
94 | self.is_visible_from_def_map(&def_map, from_module.local_id) | ||
95 | } | ||
96 | |||
97 | pub(crate) fn is_visible_from_other_crate(self) -> bool { | ||
98 | match self { | ||
99 | Visibility::Module(_) => false, | ||
100 | Visibility::Public => true, | ||
101 | } | ||
102 | } | ||
103 | |||
104 | pub(crate) fn is_visible_from_def_map( | ||
105 | self, | ||
106 | def_map: &crate::nameres::CrateDefMap, | ||
107 | from_module: crate::LocalModuleId, | ||
108 | ) -> bool { | ||
109 | let to_module = match self { | ||
110 | Visibility::Module(m) => m, | ||
111 | Visibility::Public => return true, | ||
112 | }; | ||
113 | // from_module needs to be a descendant of to_module | ||
114 | let mut ancestors = std::iter::successors(Some(from_module), |m| { | ||
115 | let parent_id = def_map[*m].parent?; | ||
116 | Some(parent_id) | ||
117 | }); | ||
118 | ancestors.any(|m| m == to_module.local_id) | ||
119 | } | ||
120 | } | ||
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs index dcca1bace..37def7c03 100644 --- a/crates/ra_hir_ty/src/display.rs +++ b/crates/ra_hir_ty/src/display.rs | |||
@@ -10,7 +10,7 @@ pub struct HirFormatter<'a, 'b, DB> { | |||
10 | buf: String, | 10 | buf: String, |
11 | curr_size: usize, | 11 | curr_size: usize, |
12 | max_size: Option<usize>, | 12 | max_size: Option<usize>, |
13 | should_display_default_types: bool, | 13 | omit_verbose_types: bool, |
14 | } | 14 | } |
15 | 15 | ||
16 | pub trait HirDisplay { | 16 | pub trait HirDisplay { |
@@ -20,7 +20,7 @@ pub trait HirDisplay { | |||
20 | where | 20 | where |
21 | Self: Sized, | 21 | Self: Sized, |
22 | { | 22 | { |
23 | HirDisplayWrapper(db, self, None, true) | 23 | HirDisplayWrapper(db, self, None, false) |
24 | } | 24 | } |
25 | 25 | ||
26 | fn display_truncated<'a, DB>( | 26 | fn display_truncated<'a, DB>( |
@@ -31,7 +31,7 @@ pub trait HirDisplay { | |||
31 | where | 31 | where |
32 | Self: Sized, | 32 | Self: Sized, |
33 | { | 33 | { |
34 | HirDisplayWrapper(db, self, max_size, false) | 34 | HirDisplayWrapper(db, self, max_size, true) |
35 | } | 35 | } |
36 | } | 36 | } |
37 | 37 | ||
@@ -74,8 +74,8 @@ where | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | pub fn should_display_default_types(&self) -> bool { | 77 | pub fn omit_verbose_types(&self) -> bool { |
78 | self.should_display_default_types | 78 | self.omit_verbose_types |
79 | } | 79 | } |
80 | } | 80 | } |
81 | 81 | ||
@@ -93,7 +93,7 @@ where | |||
93 | buf: String::with_capacity(20), | 93 | buf: String::with_capacity(20), |
94 | curr_size: 0, | 94 | curr_size: 0, |
95 | max_size: self.2, | 95 | max_size: self.2, |
96 | should_display_default_types: self.3, | 96 | omit_verbose_types: self.3, |
97 | }) | 97 | }) |
98 | } | 98 | } |
99 | } | 99 | } |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 48abf97c9..55b6dd836 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -821,6 +821,8 @@ impl TypeWalk for Ty { | |||
821 | } | 821 | } |
822 | } | 822 | } |
823 | 823 | ||
824 | const TYPE_HINT_TRUNCATION: &str = "…"; | ||
825 | |||
824 | impl HirDisplay for &Ty { | 826 | impl HirDisplay for &Ty { |
825 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 827 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
826 | HirDisplay::hir_fmt(*self, f) | 828 | HirDisplay::hir_fmt(*self, f) |
@@ -830,7 +832,7 @@ impl HirDisplay for &Ty { | |||
830 | impl HirDisplay for ApplicationTy { | 832 | impl HirDisplay for ApplicationTy { |
831 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 833 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
832 | if f.should_truncate() { | 834 | if f.should_truncate() { |
833 | return write!(f, "…"); | 835 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
834 | } | 836 | } |
835 | 837 | ||
836 | match self.ctor { | 838 | match self.ctor { |
@@ -908,9 +910,7 @@ impl HirDisplay for ApplicationTy { | |||
908 | write!(f, "<")?; | 910 | write!(f, "<")?; |
909 | 911 | ||
910 | let mut non_default_parameters = Vec::with_capacity(self.parameters.len()); | 912 | let mut non_default_parameters = Vec::with_capacity(self.parameters.len()); |
911 | let parameters_to_write = if f.should_display_default_types() { | 913 | let parameters_to_write = if f.omit_verbose_types() { |
912 | self.parameters.0.as_ref() | ||
913 | } else { | ||
914 | match self | 914 | match self |
915 | .ctor | 915 | .ctor |
916 | .as_generic_def() | 916 | .as_generic_def() |
@@ -935,6 +935,8 @@ impl HirDisplay for ApplicationTy { | |||
935 | &non_default_parameters | 935 | &non_default_parameters |
936 | } | 936 | } |
937 | } | 937 | } |
938 | } else { | ||
939 | self.parameters.0.as_ref() | ||
938 | }; | 940 | }; |
939 | 941 | ||
940 | f.write_joined(parameters_to_write, ", ")?; | 942 | f.write_joined(parameters_to_write, ", ")?; |
@@ -959,9 +961,16 @@ impl HirDisplay for ApplicationTy { | |||
959 | let sig = self.parameters[0] | 961 | let sig = self.parameters[0] |
960 | .callable_sig(f.db) | 962 | .callable_sig(f.db) |
961 | .expect("first closure parameter should contain signature"); | 963 | .expect("first closure parameter should contain signature"); |
962 | write!(f, "|")?; | 964 | let return_type_hint = sig.ret().display(f.db); |
963 | f.write_joined(sig.params(), ", ")?; | 965 | if sig.params().is_empty() { |
964 | write!(f, "| -> {}", sig.ret().display(f.db))?; | 966 | write!(f, "|| -> {}", return_type_hint)?; |
967 | } else if f.omit_verbose_types() { | ||
968 | write!(f, "|{}| -> {}", TYPE_HINT_TRUNCATION, return_type_hint)?; | ||
969 | } else { | ||
970 | write!(f, "|")?; | ||
971 | f.write_joined(sig.params(), ", ")?; | ||
972 | write!(f, "| -> {}", return_type_hint)?; | ||
973 | }; | ||
965 | } | 974 | } |
966 | } | 975 | } |
967 | Ok(()) | 976 | Ok(()) |
@@ -971,7 +980,7 @@ impl HirDisplay for ApplicationTy { | |||
971 | impl HirDisplay for ProjectionTy { | 980 | impl HirDisplay for ProjectionTy { |
972 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 981 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
973 | if f.should_truncate() { | 982 | if f.should_truncate() { |
974 | return write!(f, "…"); | 983 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
975 | } | 984 | } |
976 | 985 | ||
977 | let trait_name = f.db.trait_data(self.trait_(f.db)).name.clone(); | 986 | let trait_name = f.db.trait_data(self.trait_(f.db)).name.clone(); |
@@ -989,7 +998,7 @@ impl HirDisplay for ProjectionTy { | |||
989 | impl HirDisplay for Ty { | 998 | impl HirDisplay for Ty { |
990 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 999 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
991 | if f.should_truncate() { | 1000 | if f.should_truncate() { |
992 | return write!(f, "…"); | 1001 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
993 | } | 1002 | } |
994 | 1003 | ||
995 | match self { | 1004 | match self { |
@@ -1074,7 +1083,7 @@ impl HirDisplay for Ty { | |||
1074 | impl TraitRef { | 1083 | impl TraitRef { |
1075 | fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { | 1084 | fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { |
1076 | if f.should_truncate() { | 1085 | if f.should_truncate() { |
1077 | return write!(f, "…"); | 1086 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
1078 | } | 1087 | } |
1079 | 1088 | ||
1080 | self.substs[0].hir_fmt(f)?; | 1089 | self.substs[0].hir_fmt(f)?; |
@@ -1108,7 +1117,7 @@ impl HirDisplay for &GenericPredicate { | |||
1108 | impl HirDisplay for GenericPredicate { | 1117 | impl HirDisplay for GenericPredicate { |
1109 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 1118 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
1110 | if f.should_truncate() { | 1119 | if f.should_truncate() { |
1111 | return write!(f, "…"); | 1120 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
1112 | } | 1121 | } |
1113 | 1122 | ||
1114 | match self { | 1123 | match self { |
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index 294964887..210a685e4 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::Type; | 3 | use hir::{HasVisibility, Type}; |
4 | 4 | ||
5 | use crate::completion::completion_item::CompletionKind; | 5 | use crate::completion::completion_item::CompletionKind; |
6 | use crate::{ | 6 | use crate::{ |
@@ -38,9 +38,15 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { | |||
38 | fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { | 38 | fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { |
39 | for receiver in receiver.autoderef(ctx.db) { | 39 | for receiver in receiver.autoderef(ctx.db) { |
40 | for (field, ty) in receiver.fields(ctx.db) { | 40 | for (field, ty) in receiver.fields(ctx.db) { |
41 | if ctx.module.map_or(false, |m| !field.is_visible_from(ctx.db, m)) { | ||
42 | // Skip private field. FIXME: If the definition location of the | ||
43 | // field is editable, we should show the completion | ||
44 | continue; | ||
45 | } | ||
41 | acc.add_field(ctx, field, &ty); | 46 | acc.add_field(ctx, field, &ty); |
42 | } | 47 | } |
43 | for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() { | 48 | for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() { |
49 | // FIXME: Handle visibility | ||
44 | acc.add_tuple_field(ctx, i, &ty); | 50 | acc.add_tuple_field(ctx, i, &ty); |
45 | } | 51 | } |
46 | } | 52 | } |
@@ -187,6 +193,55 @@ mod tests { | |||
187 | } | 193 | } |
188 | 194 | ||
189 | #[test] | 195 | #[test] |
196 | fn test_struct_field_visibility_private() { | ||
197 | assert_debug_snapshot!( | ||
198 | do_ref_completion( | ||
199 | r" | ||
200 | mod inner { | ||
201 | struct A { | ||
202 | private_field: u32, | ||
203 | pub pub_field: u32, | ||
204 | pub(crate) crate_field: u32, | ||
205 | pub(super) super_field: u32, | ||
206 | } | ||
207 | } | ||
208 | fn foo(a: inner::A) { | ||
209 | a.<|> | ||
210 | } | ||
211 | ", | ||
212 | ), | ||
213 | @r###" | ||
214 | [ | ||
215 | CompletionItem { | ||
216 | label: "crate_field", | ||
217 | source_range: [313; 313), | ||
218 | delete: [313; 313), | ||
219 | insert: "crate_field", | ||
220 | kind: Field, | ||
221 | detail: "u32", | ||
222 | }, | ||
223 | CompletionItem { | ||
224 | label: "pub_field", | ||
225 | source_range: [313; 313), | ||
226 | delete: [313; 313), | ||
227 | insert: "pub_field", | ||
228 | kind: Field, | ||
229 | detail: "u32", | ||
230 | }, | ||
231 | CompletionItem { | ||
232 | label: "super_field", | ||
233 | source_range: [313; 313), | ||
234 | delete: [313; 313), | ||
235 | insert: "super_field", | ||
236 | kind: Field, | ||
237 | detail: "u32", | ||
238 | }, | ||
239 | ] | ||
240 | "### | ||
241 | ); | ||
242 | } | ||
243 | |||
244 | #[test] | ||
190 | fn test_method_completion() { | 245 | fn test_method_completion() { |
191 | assert_debug_snapshot!( | 246 | assert_debug_snapshot!( |
192 | do_ref_completion( | 247 | do_ref_completion( |
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index c5e406977..977aafc51 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -293,7 +293,7 @@ fn main() { | |||
293 | } | 293 | } |
294 | 294 | ||
295 | #[test] | 295 | #[test] |
296 | fn closure_parameter() { | 296 | fn closure_parameters() { |
297 | let (analysis, file_id) = single_file( | 297 | let (analysis, file_id) = single_file( |
298 | r#" | 298 | r#" |
299 | fn main() { | 299 | fn main() { |
@@ -301,6 +301,11 @@ fn main() { | |||
301 | (0..2).for_each(|increment| { | 301 | (0..2).for_each(|increment| { |
302 | start += increment; | 302 | start += increment; |
303 | }) | 303 | }) |
304 | |||
305 | let multiply = |a, b, c, d| a * b * c * d; | ||
306 | let _: i32 = multiply(1, 2, 3, 4); | ||
307 | |||
308 | let return_42 = || 42; | ||
304 | }"#, | 309 | }"#, |
305 | ); | 310 | ); |
306 | 311 | ||
@@ -316,6 +321,36 @@ fn main() { | |||
316 | kind: TypeHint, | 321 | kind: TypeHint, |
317 | label: "i32", | 322 | label: "i32", |
318 | }, | 323 | }, |
324 | InlayHint { | ||
325 | range: [114; 122), | ||
326 | kind: TypeHint, | ||
327 | label: "|…| -> i32", | ||
328 | }, | ||
329 | InlayHint { | ||
330 | range: [126; 127), | ||
331 | kind: TypeHint, | ||
332 | label: "i32", | ||
333 | }, | ||
334 | InlayHint { | ||
335 | range: [129; 130), | ||
336 | kind: TypeHint, | ||
337 | label: "i32", | ||
338 | }, | ||
339 | InlayHint { | ||
340 | range: [132; 133), | ||
341 | kind: TypeHint, | ||
342 | label: "i32", | ||
343 | }, | ||
344 | InlayHint { | ||
345 | range: [135; 136), | ||
346 | kind: TypeHint, | ||
347 | label: "i32", | ||
348 | }, | ||
349 | InlayHint { | ||
350 | range: [201; 210), | ||
351 | kind: TypeHint, | ||
352 | label: "|| -> i32", | ||
353 | }, | ||
319 | ] | 354 | ] |
320 | "### | 355 | "### |
321 | ); | 356 | ); |
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index c862d3912..1b3c246c7 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -165,7 +165,7 @@ impl CargoWorkspace { | |||
165 | // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` | 165 | // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` |
166 | // https://github.com/oli-obk/cargo_metadata/issues/79 | 166 | // https://github.com/oli-obk/cargo_metadata/issues/79 |
167 | meta.features(CargoOpt::NoDefaultFeatures); | 167 | meta.features(CargoOpt::NoDefaultFeatures); |
168 | } else { | 168 | } else if cargo_features.features.len() > 0 { |
169 | meta.features(CargoOpt::SomeFeatures(cargo_features.features.clone())); | 169 | meta.features(CargoOpt::SomeFeatures(cargo_features.features.clone())); |
170 | } | 170 | } |
171 | if let Some(parent) = cargo_toml.parent() { | 171 | if let Some(parent) = cargo_toml.parent() { |
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 277532a8c..89cb9a9f3 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -17,7 +17,9 @@ use crate::{ | |||
17 | 17 | ||
18 | pub use self::{ | 18 | pub use self::{ |
19 | expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp}, | 19 | expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp}, |
20 | extensions::{FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind}, | 20 | extensions::{ |
21 | FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind, VisibilityKind, | ||
22 | }, | ||
21 | generated::*, | 23 | generated::*, |
22 | tokens::*, | 24 | tokens::*, |
23 | traits::*, | 25 | traits::*, |
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index baaef3023..d9666cdca 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs | |||
@@ -413,3 +413,32 @@ impl ast::TraitDef { | |||
413 | self.syntax().children_with_tokens().any(|t| t.kind() == T![auto]) | 413 | self.syntax().children_with_tokens().any(|t| t.kind() == T![auto]) |
414 | } | 414 | } |
415 | } | 415 | } |
416 | |||
417 | pub enum VisibilityKind { | ||
418 | In(ast::Path), | ||
419 | PubCrate, | ||
420 | PubSuper, | ||
421 | Pub, | ||
422 | } | ||
423 | |||
424 | impl ast::Visibility { | ||
425 | pub fn kind(&self) -> VisibilityKind { | ||
426 | if let Some(path) = children(self).next() { | ||
427 | VisibilityKind::In(path) | ||
428 | } else if self.is_pub_crate() { | ||
429 | VisibilityKind::PubCrate | ||
430 | } else if self.is_pub_super() { | ||
431 | VisibilityKind::PubSuper | ||
432 | } else { | ||
433 | VisibilityKind::Pub | ||
434 | } | ||
435 | } | ||
436 | |||
437 | fn is_pub_crate(&self) -> bool { | ||
438 | self.syntax().children_with_tokens().any(|it| it.kind() == T![crate]) | ||
439 | } | ||
440 | |||
441 | fn is_pub_super(&self) -> bool { | ||
442 | self.syntax().children_with_tokens().any(|it| it.kind() == T![super]) | ||
443 | } | ||
444 | } | ||
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 9f9d6e63c..e64c83d33 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -1064,6 +1064,7 @@ impl AstNode for ExternCrateItem { | |||
1064 | } | 1064 | } |
1065 | } | 1065 | } |
1066 | impl ast::AttrsOwner for ExternCrateItem {} | 1066 | impl ast::AttrsOwner for ExternCrateItem {} |
1067 | impl ast::VisibilityOwner for ExternCrateItem {} | ||
1067 | impl ExternCrateItem { | 1068 | impl ExternCrateItem { |
1068 | pub fn name_ref(&self) -> Option<NameRef> { | 1069 | pub fn name_ref(&self) -> Option<NameRef> { |
1069 | AstChildren::new(&self.syntax).next() | 1070 | AstChildren::new(&self.syntax).next() |
@@ -2006,6 +2007,7 @@ impl AstNode for ModuleItem { | |||
2006 | } | 2007 | } |
2007 | } | 2008 | } |
2008 | impl ast::AttrsOwner for ModuleItem {} | 2009 | impl ast::AttrsOwner for ModuleItem {} |
2010 | impl ast::VisibilityOwner for ModuleItem {} | ||
2009 | impl ModuleItem {} | 2011 | impl ModuleItem {} |
2010 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 2012 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
2011 | pub struct Name { | 2013 | pub struct Name { |
@@ -3893,6 +3895,7 @@ impl AstNode for UseItem { | |||
3893 | } | 3895 | } |
3894 | } | 3896 | } |
3895 | impl ast::AttrsOwner for UseItem {} | 3897 | impl ast::AttrsOwner for UseItem {} |
3898 | impl ast::VisibilityOwner for UseItem {} | ||
3896 | impl UseItem { | 3899 | impl UseItem { |
3897 | pub fn use_tree(&self) -> Option<UseTree> { | 3900 | pub fn use_tree(&self) -> Option<UseTree> { |
3898 | AstChildren::new(&self.syntax).next() | 3901 | AstChildren::new(&self.syntax).next() |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 08aafb610..e43a724f0 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -412,7 +412,7 @@ Grammar( | |||
412 | "ModuleItem": ( | 412 | "ModuleItem": ( |
413 | enum: ["StructDef", "UnionDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock", | 413 | enum: ["StructDef", "UnionDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock", |
414 | "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ], | 414 | "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ], |
415 | traits: ["AttrsOwner"], | 415 | traits: ["AttrsOwner", "VisibilityOwner"], |
416 | ), | 416 | ), |
417 | "ImplItem": ( | 417 | "ImplItem": ( |
418 | enum: ["FnDef", "TypeAliasDef", "ConstDef"], | 418 | enum: ["FnDef", "TypeAliasDef", "ConstDef"], |
@@ -683,7 +683,7 @@ Grammar( | |||
683 | ] | 683 | ] |
684 | ), | 684 | ), |
685 | "UseItem": ( | 685 | "UseItem": ( |
686 | traits: ["AttrsOwner"], | 686 | traits: ["AttrsOwner", "VisibilityOwner"], |
687 | options: [ "UseTree" ], | 687 | options: [ "UseTree" ], |
688 | ), | 688 | ), |
689 | "UseTree": ( | 689 | "UseTree": ( |
@@ -696,7 +696,7 @@ Grammar( | |||
696 | collections: [("use_trees", "UseTree")] | 696 | collections: [("use_trees", "UseTree")] |
697 | ), | 697 | ), |
698 | "ExternCrateItem": ( | 698 | "ExternCrateItem": ( |
699 | traits: ["AttrsOwner"], | 699 | traits: ["AttrsOwner", "VisibilityOwner"], |
700 | options: ["NameRef", "Alias"], | 700 | options: ["NameRef", "Alias"], |
701 | ), | 701 | ), |
702 | "ArgList": ( | 702 | "ArgList": ( |
diff --git a/docs/user/assists.md b/docs/user/assists.md index 334ba450f..ecf206f71 100644 --- a/docs/user/assists.md +++ b/docs/user/assists.md | |||
@@ -98,26 +98,26 @@ Adds scaffold for overriding default impl members. | |||
98 | 98 | ||
99 | ```rust | 99 | ```rust |
100 | // BEFORE | 100 | // BEFORE |
101 | trait T { | 101 | trait Trait { |
102 | Type X; | 102 | Type X; |
103 | fn foo(&self); | 103 | fn foo(&self); |
104 | fn bar(&self) {} | 104 | fn bar(&self) {} |
105 | } | 105 | } |
106 | 106 | ||
107 | impl T for () { | 107 | impl Trait for () { |
108 | Type X = (); | 108 | Type X = (); |
109 | fn foo(&self) {}┃ | 109 | fn foo(&self) {}┃ |
110 | 110 | ||
111 | } | 111 | } |
112 | 112 | ||
113 | // AFTER | 113 | // AFTER |
114 | trait T { | 114 | trait Trait { |
115 | Type X; | 115 | Type X; |
116 | fn foo(&self); | 116 | fn foo(&self); |
117 | fn bar(&self) {} | 117 | fn bar(&self) {} |
118 | } | 118 | } |
119 | 119 | ||
120 | impl T for () { | 120 | impl Trait for () { |
121 | Type X = (); | 121 | Type X = (); |
122 | fn foo(&self) {} | 122 | fn foo(&self) {} |
123 | fn bar(&self) {} | 123 | fn bar(&self) {} |
@@ -131,25 +131,25 @@ Adds scaffold for required impl members. | |||
131 | 131 | ||
132 | ```rust | 132 | ```rust |
133 | // BEFORE | 133 | // BEFORE |
134 | trait T { | 134 | trait Trait<T> { |
135 | Type X; | 135 | Type X; |
136 | fn foo(&self); | 136 | fn foo(&self) -> T; |
137 | fn bar(&self) {} | 137 | fn bar(&self) {} |
138 | } | 138 | } |
139 | 139 | ||
140 | impl T for () {┃ | 140 | impl Trait<u32> for () {┃ |
141 | 141 | ||
142 | } | 142 | } |
143 | 143 | ||
144 | // AFTER | 144 | // AFTER |
145 | trait T { | 145 | trait Trait<T> { |
146 | Type X; | 146 | Type X; |
147 | fn foo(&self); | 147 | fn foo(&self) -> T; |
148 | fn bar(&self) {} | 148 | fn bar(&self) {} |
149 | } | 149 | } |
150 | 150 | ||
151 | impl T for () { | 151 | impl Trait<u32> for () { |
152 | fn foo(&self) { unimplemented!() } | 152 | fn foo(&self) -> u32 { unimplemented!() } |
153 | 153 | ||
154 | } | 154 | } |
155 | ``` | 155 | ``` |
diff --git a/xtask/tests/tidy-tests/cli.rs b/xtask/tests/tidy-tests/cli.rs index 573ffadbf..f9ca45292 100644 --- a/xtask/tests/tidy-tests/cli.rs +++ b/xtask/tests/tidy-tests/cli.rs | |||
@@ -43,7 +43,7 @@ fn no_todo() { | |||
43 | return; | 43 | return; |
44 | } | 44 | } |
45 | let text = std::fs::read_to_string(e.path()).unwrap(); | 45 | let text = std::fs::read_to_string(e.path()).unwrap(); |
46 | if text.contains("TODO") || text.contains("TOOD") { | 46 | if text.contains("TODO") || text.contains("TOOD") || text.contains("todo!") { |
47 | panic!( | 47 | panic!( |
48 | "\nTODO markers should not be committed to the master branch,\n\ | 48 | "\nTODO markers should not be committed to the master branch,\n\ |
49 | use FIXME instead\n\ | 49 | use FIXME instead\n\ |