diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-12-22 21:42:54 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-12-22 21:42:54 +0000 |
commit | 60aa4d12f95477565d5b01f122d2c9dd845015b4 (patch) | |
tree | 86f6d29653ba7e548f2a321b2ecdb20e7dc366f4 | |
parent | 78f7683b9a1c6192b4828ceedb14ed498b241263 (diff) | |
parent | e424545c0f5cbaf135c52764169ea20df7d07d35 (diff) |
Merge #2648
2648: Rudimentary name resolution for local items r=matklad a=matklad
Co-authored-by: Aleksey Kladov <[email protected]>
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_scope.rs | 27 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/path_resolution.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir_def/src/resolver.rs | 103 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 12 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_scope.rs | 37 |
7 files changed, 163 insertions, 65 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 754924050..5323af097 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -494,45 +494,57 @@ where | |||
494 | fn collect_block_items(&mut self, block: &ast::Block) { | 494 | fn collect_block_items(&mut self, block: &ast::Block) { |
495 | let container = ContainerId::DefWithBodyId(self.def); | 495 | let container = ContainerId::DefWithBodyId(self.def); |
496 | for item in block.items() { | 496 | for item in block.items() { |
497 | let def: ModuleDefId = match item { | 497 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { |
498 | ast::ModuleItem::FnDef(def) => { | 498 | ast::ModuleItem::FnDef(def) => { |
499 | let ast_id = self.expander.ast_id(&def); | 499 | let ast_id = self.expander.ast_id(&def); |
500 | FunctionLoc { container: container.into(), ast_id }.intern(self.db).into() | 500 | ( |
501 | FunctionLoc { container: container.into(), ast_id }.intern(self.db).into(), | ||
502 | def.name(), | ||
503 | ) | ||
501 | } | 504 | } |
502 | ast::ModuleItem::TypeAliasDef(def) => { | 505 | ast::ModuleItem::TypeAliasDef(def) => { |
503 | let ast_id = self.expander.ast_id(&def); | 506 | let ast_id = self.expander.ast_id(&def); |
504 | TypeAliasLoc { container: container.into(), ast_id }.intern(self.db).into() | 507 | ( |
508 | TypeAliasLoc { container: container.into(), ast_id }.intern(self.db).into(), | ||
509 | def.name(), | ||
510 | ) | ||
505 | } | 511 | } |
506 | ast::ModuleItem::ConstDef(def) => { | 512 | ast::ModuleItem::ConstDef(def) => { |
507 | let ast_id = self.expander.ast_id(&def); | 513 | let ast_id = self.expander.ast_id(&def); |
508 | ConstLoc { container: container.into(), ast_id }.intern(self.db).into() | 514 | ( |
515 | ConstLoc { container: container.into(), ast_id }.intern(self.db).into(), | ||
516 | def.name(), | ||
517 | ) | ||
509 | } | 518 | } |
510 | ast::ModuleItem::StaticDef(def) => { | 519 | ast::ModuleItem::StaticDef(def) => { |
511 | let ast_id = self.expander.ast_id(&def); | 520 | let ast_id = self.expander.ast_id(&def); |
512 | StaticLoc { container, ast_id }.intern(self.db).into() | 521 | (StaticLoc { container, ast_id }.intern(self.db).into(), def.name()) |
513 | } | 522 | } |
514 | ast::ModuleItem::StructDef(def) => { | 523 | ast::ModuleItem::StructDef(def) => { |
515 | let ast_id = self.expander.ast_id(&def); | 524 | let ast_id = self.expander.ast_id(&def); |
516 | StructLoc { container, ast_id }.intern(self.db).into() | 525 | (StructLoc { container, ast_id }.intern(self.db).into(), def.name()) |
517 | } | 526 | } |
518 | ast::ModuleItem::EnumDef(def) => { | 527 | ast::ModuleItem::EnumDef(def) => { |
519 | let ast_id = self.expander.ast_id(&def); | 528 | let ast_id = self.expander.ast_id(&def); |
520 | EnumLoc { container, ast_id }.intern(self.db).into() | 529 | (EnumLoc { container, ast_id }.intern(self.db).into(), def.name()) |
521 | } | 530 | } |
522 | ast::ModuleItem::UnionDef(def) => { | 531 | ast::ModuleItem::UnionDef(def) => { |
523 | let ast_id = self.expander.ast_id(&def); | 532 | let ast_id = self.expander.ast_id(&def); |
524 | UnionLoc { container, ast_id }.intern(self.db).into() | 533 | (UnionLoc { container, ast_id }.intern(self.db).into(), def.name()) |
525 | } | 534 | } |
526 | ast::ModuleItem::TraitDef(def) => { | 535 | ast::ModuleItem::TraitDef(def) => { |
527 | let ast_id = self.expander.ast_id(&def); | 536 | let ast_id = self.expander.ast_id(&def); |
528 | TraitLoc { container, ast_id }.intern(self.db).into() | 537 | (TraitLoc { container, ast_id }.intern(self.db).into(), def.name()) |
529 | } | 538 | } |
530 | ast::ModuleItem::ImplBlock(_) | 539 | ast::ModuleItem::ImplBlock(_) |
531 | | ast::ModuleItem::UseItem(_) | 540 | | ast::ModuleItem::UseItem(_) |
532 | | ast::ModuleItem::ExternCrateItem(_) | 541 | | ast::ModuleItem::ExternCrateItem(_) |
533 | | ast::ModuleItem::Module(_) => continue, | 542 | | ast::ModuleItem::Module(_) => continue, |
534 | }; | 543 | }; |
535 | self.body.item_scope.define_def(def) | 544 | self.body.item_scope.define_def(def); |
545 | if let Some(name) = name { | ||
546 | self.body.item_scope.push_res(name.as_name(), def.into()); | ||
547 | } | ||
536 | } | 548 | } |
537 | } | 549 | } |
538 | 550 | ||
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index f1adc3b58..b0288ee8d 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -51,6 +51,12 @@ impl ItemScope { | |||
51 | self.visible.iter().chain(BUILTIN_SCOPE.iter()).map(|(n, def)| (n, *def)) | 51 | self.visible.iter().chain(BUILTIN_SCOPE.iter()).map(|(n, def)| (n, *def)) |
52 | } | 52 | } |
53 | 53 | ||
54 | pub fn entries_without_primitives<'a>( | ||
55 | &'a self, | ||
56 | ) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { | ||
57 | self.visible.iter().map(|(n, def)| (n, *def)) | ||
58 | } | ||
59 | |||
54 | pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ { | 60 | pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ { |
55 | self.defs.iter().copied() | 61 | self.defs.iter().copied() |
56 | } | 62 | } |
@@ -70,18 +76,27 @@ impl ItemScope { | |||
70 | } | 76 | } |
71 | 77 | ||
72 | /// Get a name from current module scope, legacy macros are not included | 78 | /// Get a name from current module scope, legacy macros are not included |
73 | pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&PerNs> { | 79 | pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> PerNs { |
74 | match shadow { | 80 | match shadow { |
75 | BuiltinShadowMode::Module => self.visible.get(name).or_else(|| BUILTIN_SCOPE.get(name)), | 81 | BuiltinShadowMode::Module => self |
82 | .visible | ||
83 | .get(name) | ||
84 | .or_else(|| BUILTIN_SCOPE.get(name)) | ||
85 | .copied() | ||
86 | .unwrap_or_else(PerNs::none), | ||
76 | BuiltinShadowMode::Other => { | 87 | BuiltinShadowMode::Other => { |
77 | let item = self.visible.get(name); | 88 | let item = self.visible.get(name).copied(); |
78 | if let Some(def) = item { | 89 | if let Some(def) = item { |
79 | if let Some(ModuleDefId::ModuleId(_)) = def.take_types() { | 90 | if let Some(ModuleDefId::ModuleId(_)) = def.take_types() { |
80 | return BUILTIN_SCOPE.get(name).or(item); | 91 | return BUILTIN_SCOPE |
92 | .get(name) | ||
93 | .copied() | ||
94 | .or(item) | ||
95 | .unwrap_or_else(PerNs::none); | ||
81 | } | 96 | } |
82 | } | 97 | } |
83 | 98 | ||
84 | item.or_else(|| BUILTIN_SCOPE.get(name)) | 99 | item.or_else(|| BUILTIN_SCOPE.get(name).copied()).unwrap_or_else(PerNs::none) |
85 | } | 100 | } |
86 | } | 101 | } |
87 | } | 102 | } |
@@ -109,7 +124,7 @@ impl ItemScope { | |||
109 | self.legacy_macros.insert(name, mac); | 124 | self.legacy_macros.insert(name, mac); |
110 | } | 125 | } |
111 | 126 | ||
112 | pub(crate) fn push_res(&mut self, name: Name, def: &PerNs) -> bool { | 127 | pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { |
113 | let mut changed = false; | 128 | let mut changed = false; |
114 | let existing = self.visible.entry(name.clone()).or_default(); | 129 | let existing = self.visible.entry(name.clone()).or_default(); |
115 | 130 | ||
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 4f1fd4801..b9f40d3dd 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -446,7 +446,7 @@ where | |||
446 | let scope = &mut self.def_map.modules[module_id].scope; | 446 | let scope = &mut self.def_map.modules[module_id].scope; |
447 | let mut changed = false; | 447 | let mut changed = false; |
448 | for (name, res) in resolutions { | 448 | for (name, res) in resolutions { |
449 | changed |= scope.push_res(name.clone(), res); | 449 | changed |= scope.push_res(name.clone(), *res); |
450 | } | 450 | } |
451 | 451 | ||
452 | if !changed { | 452 | if !changed { |
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 378d49455..695014c7b 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs | |||
@@ -180,13 +180,7 @@ impl CrateDefMap { | |||
180 | } | 180 | } |
181 | 181 | ||
182 | // Since it is a qualified path here, it should not contains legacy macros | 182 | // Since it is a qualified path here, it should not contains legacy macros |
183 | match self[module.local_id].scope.get(&segment, prefer_module(i)) { | 183 | self[module.local_id].scope.get(&segment, prefer_module(i)) |
184 | Some(def) => *def, | ||
185 | _ => { | ||
186 | log::debug!("path segment {:?} not found", segment); | ||
187 | return ResolvePathResult::empty(ReachedFixedPoint::No); | ||
188 | } | ||
189 | } | ||
190 | } | 184 | } |
191 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { | 185 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { |
192 | // enum variant | 186 | // enum variant |
@@ -243,7 +237,7 @@ impl CrateDefMap { | |||
243 | // - std prelude | 237 | // - std prelude |
244 | let from_legacy_macro = | 238 | let from_legacy_macro = |
245 | self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); | 239 | self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); |
246 | let from_scope = self[module].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none); | 240 | let from_scope = self[module].scope.get(name, shadow); |
247 | let from_extern_prelude = | 241 | let from_extern_prelude = |
248 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); | 242 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); |
249 | let from_prelude = self.resolve_in_prelude(db, name, shadow); | 243 | let from_prelude = self.resolve_in_prelude(db, name, shadow); |
@@ -256,8 +250,7 @@ impl CrateDefMap { | |||
256 | name: &Name, | 250 | name: &Name, |
257 | shadow: BuiltinShadowMode, | 251 | shadow: BuiltinShadowMode, |
258 | ) -> PerNs { | 252 | ) -> PerNs { |
259 | let from_crate_root = | 253 | let from_crate_root = self[self.root].scope.get(name, shadow); |
260 | self[self.root].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none); | ||
261 | let from_extern_prelude = self.resolve_name_in_extern_prelude(name); | 254 | let from_extern_prelude = self.resolve_name_in_extern_prelude(name); |
262 | 255 | ||
263 | from_crate_root.or(from_extern_prelude) | 256 | from_crate_root.or(from_extern_prelude) |
@@ -278,7 +271,7 @@ impl CrateDefMap { | |||
278 | keep = db.crate_def_map(prelude.krate); | 271 | keep = db.crate_def_map(prelude.krate); |
279 | &keep | 272 | &keep |
280 | }; | 273 | }; |
281 | def_map[prelude.local_id].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none) | 274 | def_map[prelude.local_id].scope.get(name, shadow) |
282 | } else { | 275 | } else { |
283 | PerNs::none() | 276 | PerNs::none() |
284 | } | 277 | } |
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index e70049617..cf3c33d78 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -10,6 +10,7 @@ use rustc_hash::FxHashSet; | |||
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | body::scope::{ExprScopes, ScopeId}, | 12 | body::scope::{ExprScopes, ScopeId}, |
13 | body::Body, | ||
13 | builtin_type::BuiltinType, | 14 | builtin_type::BuiltinType, |
14 | db::DefDatabase, | 15 | db::DefDatabase, |
15 | expr::{ExprId, PatId}, | 16 | expr::{ExprId, PatId}, |
@@ -55,6 +56,8 @@ enum Scope { | |||
55 | AdtScope(AdtId), | 56 | AdtScope(AdtId), |
56 | /// Local bindings | 57 | /// Local bindings |
57 | ExprScope(ExprScope), | 58 | ExprScope(ExprScope), |
59 | /// Temporary hack to support local items. | ||
60 | LocalItemsScope(Arc<Body>), | ||
58 | } | 61 | } |
59 | 62 | ||
60 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 63 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -149,7 +152,13 @@ impl Resolver { | |||
149 | for scope in self.scopes.iter().rev() { | 152 | for scope in self.scopes.iter().rev() { |
150 | match scope { | 153 | match scope { |
151 | Scope::ExprScope(_) => continue, | 154 | Scope::ExprScope(_) => continue, |
152 | Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, | 155 | Scope::GenericParams { .. } |
156 | | Scope::ImplBlockScope(_) | ||
157 | | Scope::LocalItemsScope(_) | ||
158 | if skip_to_mod => | ||
159 | { | ||
160 | continue | ||
161 | } | ||
153 | 162 | ||
154 | Scope::GenericParams { params, def } => { | 163 | Scope::GenericParams { params, def } => { |
155 | if let Some(local_id) = params.find_by_name(first_name) { | 164 | if let Some(local_id) = params.find_by_name(first_name) { |
@@ -179,25 +188,35 @@ impl Resolver { | |||
179 | &path, | 188 | &path, |
180 | BuiltinShadowMode::Other, | 189 | BuiltinShadowMode::Other, |
181 | ); | 190 | ); |
182 | let res = match module_def.take_types()? { | 191 | let res = to_type_ns(module_def)?; |
183 | ModuleDefId::AdtId(it) => TypeNs::AdtId(it), | ||
184 | ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), | ||
185 | |||
186 | ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), | ||
187 | ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), | ||
188 | |||
189 | ModuleDefId::TraitId(it) => TypeNs::TraitId(it), | ||
190 | |||
191 | ModuleDefId::FunctionId(_) | ||
192 | | ModuleDefId::ConstId(_) | ||
193 | | ModuleDefId::StaticId(_) | ||
194 | | ModuleDefId::ModuleId(_) => return None, | ||
195 | }; | ||
196 | return Some((res, idx)); | 192 | return Some((res, idx)); |
197 | } | 193 | } |
194 | Scope::LocalItemsScope(body) => { | ||
195 | let def = body.item_scope.get(first_name, BuiltinShadowMode::Other); | ||
196 | if let Some(res) = to_type_ns(def) { | ||
197 | return Some((res, None)); | ||
198 | } | ||
199 | } | ||
198 | } | 200 | } |
199 | } | 201 | } |
200 | None | 202 | return None; |
203 | fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> { | ||
204 | let res = match per_ns.take_types()? { | ||
205 | ModuleDefId::AdtId(it) => TypeNs::AdtId(it), | ||
206 | ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), | ||
207 | |||
208 | ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), | ||
209 | ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), | ||
210 | |||
211 | ModuleDefId::TraitId(it) => TypeNs::TraitId(it), | ||
212 | |||
213 | ModuleDefId::FunctionId(_) | ||
214 | | ModuleDefId::ConstId(_) | ||
215 | | ModuleDefId::StaticId(_) | ||
216 | | ModuleDefId::ModuleId(_) => return None, | ||
217 | }; | ||
218 | Some(res) | ||
219 | } | ||
201 | } | 220 | } |
202 | 221 | ||
203 | pub fn resolve_path_in_type_ns_fully( | 222 | pub fn resolve_path_in_type_ns_fully( |
@@ -227,6 +246,7 @@ impl Resolver { | |||
227 | | Scope::ExprScope(_) | 246 | | Scope::ExprScope(_) |
228 | | Scope::GenericParams { .. } | 247 | | Scope::GenericParams { .. } |
229 | | Scope::ImplBlockScope(_) | 248 | | Scope::ImplBlockScope(_) |
249 | | Scope::LocalItemsScope(_) | ||
230 | if skip_to_mod => | 250 | if skip_to_mod => |
231 | { | 251 | { |
232 | continue | 252 | continue |
@@ -276,20 +296,7 @@ impl Resolver { | |||
276 | ); | 296 | ); |
277 | return match idx { | 297 | return match idx { |
278 | None => { | 298 | None => { |
279 | let value = match module_def.take_values()? { | 299 | let value = to_value_ns(module_def)?; |
280 | ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), | ||
281 | ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), | ||
282 | ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), | ||
283 | ModuleDefId::ConstId(it) => ValueNs::ConstId(it), | ||
284 | ModuleDefId::StaticId(it) => ValueNs::StaticId(it), | ||
285 | |||
286 | ModuleDefId::AdtId(AdtId::EnumId(_)) | ||
287 | | ModuleDefId::AdtId(AdtId::UnionId(_)) | ||
288 | | ModuleDefId::TraitId(_) | ||
289 | | ModuleDefId::TypeAliasId(_) | ||
290 | | ModuleDefId::BuiltinType(_) | ||
291 | | ModuleDefId::ModuleId(_) => return None, | ||
292 | }; | ||
293 | Some(ResolveValueResult::ValueNs(value)) | 300 | Some(ResolveValueResult::ValueNs(value)) |
294 | } | 301 | } |
295 | Some(idx) => { | 302 | Some(idx) => { |
@@ -309,9 +316,33 @@ impl Resolver { | |||
309 | } | 316 | } |
310 | }; | 317 | }; |
311 | } | 318 | } |
319 | Scope::LocalItemsScope(body) => { | ||
320 | let def = body.item_scope.get(first_name, BuiltinShadowMode::Other); | ||
321 | if let Some(res) = to_value_ns(def) { | ||
322 | return Some(ResolveValueResult::ValueNs(res)); | ||
323 | } | ||
324 | } | ||
312 | } | 325 | } |
313 | } | 326 | } |
314 | None | 327 | return None; |
328 | |||
329 | fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> { | ||
330 | let res = match per_ns.take_values()? { | ||
331 | ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), | ||
332 | ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), | ||
333 | ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), | ||
334 | ModuleDefId::ConstId(it) => ValueNs::ConstId(it), | ||
335 | ModuleDefId::StaticId(it) => ValueNs::StaticId(it), | ||
336 | |||
337 | ModuleDefId::AdtId(AdtId::EnumId(_)) | ||
338 | | ModuleDefId::AdtId(AdtId::UnionId(_)) | ||
339 | | ModuleDefId::TraitId(_) | ||
340 | | ModuleDefId::TypeAliasId(_) | ||
341 | | ModuleDefId::BuiltinType(_) | ||
342 | | ModuleDefId::ModuleId(_) => return None, | ||
343 | }; | ||
344 | Some(res) | ||
345 | } | ||
315 | } | 346 | } |
316 | 347 | ||
317 | pub fn resolve_path_in_value_ns_fully( | 348 | pub fn resolve_path_in_value_ns_fully( |
@@ -429,6 +460,11 @@ impl Scope { | |||
429 | }); | 460 | }); |
430 | } | 461 | } |
431 | } | 462 | } |
463 | Scope::LocalItemsScope(body) => { | ||
464 | body.item_scope.entries_without_primitives().for_each(|(name, def)| { | ||
465 | f(name.clone(), ScopeDef::PerNs(def)); | ||
466 | }) | ||
467 | } | ||
432 | Scope::GenericParams { params, def } => { | 468 | Scope::GenericParams { params, def } => { |
433 | for (local_id, param) in params.types.iter() { | 469 | for (local_id, param) in params.types.iter() { |
434 | f( | 470 | f( |
@@ -464,6 +500,7 @@ pub fn resolver_for_scope( | |||
464 | scope_id: Option<ScopeId>, | 500 | scope_id: Option<ScopeId>, |
465 | ) -> Resolver { | 501 | ) -> Resolver { |
466 | let mut r = owner.resolver(db); | 502 | let mut r = owner.resolver(db); |
503 | r = r.push_local_items_scope(db.body(owner)); | ||
467 | let scopes = db.expr_scopes(owner); | 504 | let scopes = db.expr_scopes(owner); |
468 | let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); | 505 | let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); |
469 | for scope in scope_chain.into_iter().rev() { | 506 | for scope in scope_chain.into_iter().rev() { |
@@ -499,6 +536,10 @@ impl Resolver { | |||
499 | self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) | 536 | self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) |
500 | } | 537 | } |
501 | 538 | ||
539 | fn push_local_items_scope(self, body: Arc<Body>) -> Resolver { | ||
540 | self.push_scope(Scope::LocalItemsScope(body)) | ||
541 | } | ||
542 | |||
502 | fn push_expr_scope( | 543 | fn push_expr_scope( |
503 | self, | 544 | self, |
504 | owner: DefWithBodyId, | 545 | owner: DefWithBodyId, |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 6fe647a5e..3e5e163e3 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -1512,8 +1512,8 @@ fn test() { | |||
1512 | [49; 50) '0': u32 | 1512 | [49; 50) '0': u32 |
1513 | [80; 83) '101': u32 | 1513 | [80; 83) '101': u32 |
1514 | [95; 213) '{ ...NST; }': () | 1514 | [95; 213) '{ ...NST; }': () |
1515 | [138; 139) 'x': {unknown} | 1515 | [138; 139) 'x': u32 |
1516 | [142; 153) 'LOCAL_CONST': {unknown} | 1516 | [142; 153) 'LOCAL_CONST': u32 |
1517 | [163; 164) 'z': u32 | 1517 | [163; 164) 'z': u32 |
1518 | [167; 179) 'GLOBAL_CONST': u32 | 1518 | [167; 179) 'GLOBAL_CONST': u32 |
1519 | [189; 191) 'id': u32 | 1519 | [189; 191) 'id': u32 |
@@ -1541,10 +1541,10 @@ fn test() { | |||
1541 | [29; 32) '101': u32 | 1541 | [29; 32) '101': u32 |
1542 | [70; 73) '101': u32 | 1542 | [70; 73) '101': u32 |
1543 | [85; 280) '{ ...MUT; }': () | 1543 | [85; 280) '{ ...MUT; }': () |
1544 | [173; 174) 'x': {unknown} | 1544 | [173; 174) 'x': u32 |
1545 | [177; 189) 'LOCAL_STATIC': {unknown} | 1545 | [177; 189) 'LOCAL_STATIC': u32 |
1546 | [199; 200) 'y': {unknown} | 1546 | [199; 200) 'y': u32 |
1547 | [203; 219) 'LOCAL_...IC_MUT': {unknown} | 1547 | [203; 219) 'LOCAL_...IC_MUT': u32 |
1548 | [229; 230) 'z': u32 | 1548 | [229; 230) 'z': u32 |
1549 | [233; 246) 'GLOBAL_STATIC': u32 | 1549 | [233; 246) 'GLOBAL_STATIC': u32 |
1550 | [256; 257) 'w': u32 | 1550 | [256; 257) 'w': u32 |
diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index d5739b58a..458d7525e 100644 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ b/crates/ra_ide/src/completion/complete_scope.rs | |||
@@ -873,4 +873,41 @@ mod tests { | |||
873 | "### | 873 | "### |
874 | ); | 874 | ); |
875 | } | 875 | } |
876 | |||
877 | #[test] | ||
878 | fn completes_local_item() { | ||
879 | assert_debug_snapshot!( | ||
880 | do_reference_completion( | ||
881 | " | ||
882 | //- /main.rs | ||
883 | fn main() { | ||
884 | return f<|>; | ||
885 | fn frobnicate() {} | ||
886 | } | ||
887 | " | ||
888 | ), | ||
889 | @r###" | ||
890 | [ | ||
891 | CompletionItem { | ||
892 | label: "frobnicate()", | ||
893 | source_range: [23; 24), | ||
894 | delete: [23; 24), | ||
895 | insert: "frobnicate()$0", | ||
896 | kind: Function, | ||
897 | lookup: "frobnicate", | ||
898 | detail: "fn frobnicate()", | ||
899 | }, | ||
900 | CompletionItem { | ||
901 | label: "main()", | ||
902 | source_range: [23; 24), | ||
903 | delete: [23; 24), | ||
904 | insert: "main()$0", | ||
905 | kind: Function, | ||
906 | lookup: "main", | ||
907 | detail: "fn main()", | ||
908 | }, | ||
909 | ] | ||
910 | "### | ||
911 | ) | ||
912 | } | ||
876 | } | 913 | } |