aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_analysis/src/completion/complete_scope.rs9
-rw-r--r--crates/ra_analysis/src/goto_defenition.rs2
-rw-r--r--crates/ra_analysis/src/imp.rs4
-rw-r--r--crates/ra_hir/src/db.rs2
-rw-r--r--crates/ra_hir/src/expr.rs363
-rw-r--r--crates/ra_hir/src/function.rs21
-rw-r--r--crates/ra_hir/src/function/scope.rs368
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/name.rs10
-rw-r--r--crates/ra_hir/src/query_definitions.rs11
-rw-r--r--crates/ra_hir/src/ty.rs19
-rw-r--r--crates/ra_syntax/src/ast/generated.rs25
-rw-r--r--crates/ra_syntax/src/grammar.ron10
13 files changed, 533 insertions, 313 deletions
diff --git a/crates/ra_analysis/src/completion/complete_scope.rs b/crates/ra_analysis/src/completion/complete_scope.rs
index 4dead3689..21d77aa97 100644
--- a/crates/ra_analysis/src/completion/complete_scope.rs
+++ b/crates/ra_analysis/src/completion/complete_scope.rs
@@ -15,7 +15,7 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) ->
15 None => return Ok(()), 15 None => return Ok(()),
16 }; 16 };
17 if let Some(function) = &ctx.function { 17 if let Some(function) = &ctx.function {
18 let scopes = function.scopes(ctx.db); 18 let scopes = function.scopes(ctx.db)?;
19 complete_fn(acc, &scopes, ctx.offset); 19 complete_fn(acc, &scopes, ctx.offset);
20 } 20 }
21 21
@@ -40,20 +40,17 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) ->
40 Ok(()) 40 Ok(())
41} 41}
42 42
43fn complete_fn(acc: &mut Completions, scopes: &hir::FnScopes, offset: TextUnit) { 43fn complete_fn(acc: &mut Completions, scopes: &hir::ScopesWithSyntaxMapping, offset: TextUnit) {
44 let mut shadowed = FxHashSet::default(); 44 let mut shadowed = FxHashSet::default();
45 scopes 45 scopes
46 .scope_chain_for_offset(offset) 46 .scope_chain_for_offset(offset)
47 .flat_map(|scope| scopes.entries(scope).iter()) 47 .flat_map(|scope| scopes.scopes.entries(scope).iter())
48 .filter(|entry| shadowed.insert(entry.name())) 48 .filter(|entry| shadowed.insert(entry.name()))
49 .for_each(|entry| { 49 .for_each(|entry| {
50 CompletionItem::new(CompletionKind::Reference, entry.name().to_string()) 50 CompletionItem::new(CompletionKind::Reference, entry.name().to_string())
51 .kind(CompletionItemKind::Binding) 51 .kind(CompletionItemKind::Binding)
52 .add_to(acc) 52 .add_to(acc)
53 }); 53 });
54 if scopes.self_param.is_some() {
55 CompletionItem::new(CompletionKind::Reference, "self").add_to(acc);
56 }
57} 54}
58 55
59#[cfg(test)] 56#[cfg(test)]
diff --git a/crates/ra_analysis/src/goto_defenition.rs b/crates/ra_analysis/src/goto_defenition.rs
index e37421f8d..68b6ac3ba 100644
--- a/crates/ra_analysis/src/goto_defenition.rs
+++ b/crates/ra_analysis/src/goto_defenition.rs
@@ -28,7 +28,7 @@ pub(crate) fn reference_defenition(
28 if let Some(fn_descr) = 28 if let Some(fn_descr) =
29 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax())? 29 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax())?
30 { 30 {
31 let scope = fn_descr.scopes(db); 31 let scope = fn_descr.scopes(db)?;
32 // First try to resolve the symbol locally 32 // First try to resolve the symbol locally
33 if let Some(entry) = scope.resolve_local_name(name_ref) { 33 if let Some(entry) = scope.resolve_local_name(name_ref) {
34 let nav = NavigationTarget { 34 let nav = NavigationTarget {
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index 6ab3c5476..5988fb779 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -157,7 +157,7 @@ impl db::RootDatabase {
157 .collect::<Vec<_>>(); 157 .collect::<Vec<_>>();
158 ret.extend( 158 ret.extend(
159 descr 159 descr
160 .scopes(self) 160 .scopes(self)?
161 .find_all_refs(binding) 161 .find_all_refs(binding)
162 .into_iter() 162 .into_iter()
163 .map(|ref_desc| (position.file_id, ref_desc.range)), 163 .map(|ref_desc| (position.file_id, ref_desc.range)),
@@ -185,7 +185,7 @@ impl db::RootDatabase {
185 position.file_id, 185 position.file_id,
186 name_ref.syntax(), 186 name_ref.syntax(),
187 )?); 187 )?);
188 let scope = descr.scopes(db); 188 let scope = descr.scopes(db)?;
189 let resolved = ctry!(scope.resolve_local_name(name_ref)); 189 let resolved = ctry!(scope.resolve_local_name(name_ref));
190 let resolved = resolved.ptr().resolve(source_file); 190 let resolved = resolved.ptr().resolve(source_file);
191 let binding = ctry!(find_node_at_offset::<ast::BindPat>( 191 let binding = ctry!(find_node_at_offset::<ast::BindPat>(
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 188b96872..aaf367e08 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -31,7 +31,7 @@ pub trait HirDatabase: SyntaxDatabase
31 use fn crate::macros::expand_macro_invocation; 31 use fn crate::macros::expand_macro_invocation;
32 } 32 }
33 33
34 fn fn_scopes(def_id: DefId) -> Arc<FnScopes> { 34 fn fn_scopes(def_id: DefId) -> Cancelable<Arc<FnScopes>> {
35 type FnScopesQuery; 35 type FnScopesQuery;
36 use fn query_definitions::fn_scopes; 36 use fn query_definitions::fn_scopes;
37 } 37 }
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 5cdcca082..5cf0f5e3f 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -4,7 +4,7 @@ use rustc_hash::FxHashMap;
4 4
5use ra_arena::{Arena, RawId, impl_arena_id}; 5use ra_arena::{Arena, RawId, impl_arena_id};
6use ra_db::{LocalSyntaxPtr, Cancelable}; 6use ra_db::{LocalSyntaxPtr, Cancelable};
7use ra_syntax::ast::{self, AstNode, LoopBodyOwner, ArgListOwner}; 7use ra_syntax::ast::{self, AstNode, LoopBodyOwner, ArgListOwner, NameOwner};
8 8
9use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName}; 9use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName};
10 10
@@ -21,7 +21,7 @@ pub struct Body {
21 /// part of the function signature, the patterns are not (they don't change 21 /// part of the function signature, the patterns are not (they don't change
22 /// the external type of the function). 22 /// the external type of the function).
23 /// 23 ///
24 /// If this `ExprTable` is for the body of a constant, this will just be 24 /// If this `Body` is for the body of a constant, this will just be
25 /// empty. 25 /// empty.
26 args: Vec<PatId>, 26 args: Vec<PatId>,
27 /// The `ExprId` of the actual body expression. 27 /// The `ExprId` of the actual body expression.
@@ -43,6 +43,43 @@ pub struct BodySyntaxMapping {
43 pat_syntax_mapping_back: FxHashMap<PatId, LocalSyntaxPtr>, 43 pat_syntax_mapping_back: FxHashMap<PatId, LocalSyntaxPtr>,
44} 44}
45 45
46impl Body {
47 pub fn expr(&self, expr: ExprId) -> &Expr {
48 &self.exprs[expr]
49 }
50
51 pub fn pat(&self, pat: PatId) -> &Pat {
52 &self.pats[pat]
53 }
54
55 pub fn args(&self) -> &[PatId] {
56 &self.args
57 }
58
59 pub fn body_expr(&self) -> ExprId {
60 self.body_expr
61 }
62}
63
64impl BodySyntaxMapping {
65 pub fn expr_syntax(&self, expr: ExprId) -> Option<LocalSyntaxPtr> {
66 self.expr_syntax_mapping_back.get(&expr).cloned()
67 }
68 pub fn syntax_expr(&self, ptr: LocalSyntaxPtr) -> Option<ExprId> {
69 self.expr_syntax_mapping.get(&ptr).cloned()
70 }
71 pub fn pat_syntax(&self, pat: PatId) -> Option<LocalSyntaxPtr> {
72 self.pat_syntax_mapping_back.get(&pat).cloned()
73 }
74 pub fn syntax_pat(&self, ptr: LocalSyntaxPtr) -> Option<PatId> {
75 self.pat_syntax_mapping.get(&ptr).cloned()
76 }
77
78 pub fn body(&self) -> &Arc<Body> {
79 &self.body
80 }
81}
82
46#[derive(Debug, Clone, Eq, PartialEq)] 83#[derive(Debug, Clone, Eq, PartialEq)]
47pub enum Expr { 84pub enum Expr {
48 /// This is produced if syntax tree does not have a required expression piece. 85 /// This is produced if syntax tree does not have a required expression piece.
@@ -113,21 +150,26 @@ pub enum Expr {
113 expr: ExprId, 150 expr: ExprId,
114 op: Option<UnaryOp>, 151 op: Option<UnaryOp>,
115 }, 152 },
153 Lambda {
154 args: Vec<PatId>,
155 arg_types: Vec<Option<TypeRef>>,
156 body: ExprId,
157 },
116} 158}
117 159
118pub type UnaryOp = ast::PrefixOp; 160pub type UnaryOp = ast::PrefixOp;
119 161
120#[derive(Debug, Clone, Eq, PartialEq)] 162#[derive(Debug, Clone, Eq, PartialEq)]
121pub struct MatchArm { 163pub struct MatchArm {
122 pats: Vec<PatId>, 164 pub pats: Vec<PatId>,
123 // guard: Option<ExprId>, // TODO 165 // guard: Option<ExprId>, // TODO
124 expr: ExprId, 166 pub expr: ExprId,
125} 167}
126 168
127#[derive(Debug, Clone, Eq, PartialEq)] 169#[derive(Debug, Clone, Eq, PartialEq)]
128pub struct StructLitField { 170pub struct StructLitField {
129 name: Name, 171 pub name: Name,
130 expr: ExprId, 172 pub expr: ExprId,
131} 173}
132 174
133#[derive(Debug, Clone, Eq, PartialEq)] 175#[derive(Debug, Clone, Eq, PartialEq)]
@@ -140,12 +182,118 @@ pub enum Statement {
140 Expr(ExprId), 182 Expr(ExprId),
141} 183}
142 184
185impl Expr {
186 pub fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) {
187 match self {
188 Expr::Missing => {}
189 Expr::Path(_) => {}
190 Expr::If {
191 condition,
192 then_branch,
193 else_branch,
194 } => {
195 f(*condition);
196 f(*then_branch);
197 if let Some(else_branch) = else_branch {
198 f(*else_branch);
199 }
200 }
201 Expr::Block { statements, tail } => {
202 for stmt in statements {
203 match stmt {
204 Statement::Let { initializer, .. } => {
205 if let Some(expr) = initializer {
206 f(*expr);
207 }
208 }
209 Statement::Expr(e) => f(*e),
210 }
211 }
212 if let Some(expr) = tail {
213 f(*expr);
214 }
215 }
216 Expr::Loop { body } => f(*body),
217 Expr::While { condition, body } => {
218 f(*condition);
219 f(*body);
220 }
221 Expr::For { iterable, body, .. } => {
222 f(*iterable);
223 f(*body);
224 }
225 Expr::Call { callee, args } => {
226 f(*callee);
227 for arg in args {
228 f(*arg);
229 }
230 }
231 Expr::MethodCall { receiver, args, .. } => {
232 f(*receiver);
233 for arg in args {
234 f(*arg);
235 }
236 }
237 Expr::Match { expr, arms } => {
238 f(*expr);
239 for arm in arms {
240 f(arm.expr);
241 }
242 }
243 Expr::Continue => {}
244 Expr::Break { expr } | Expr::Return { expr } => {
245 if let Some(expr) = expr {
246 f(*expr);
247 }
248 }
249 Expr::StructLit { fields, spread, .. } => {
250 for field in fields {
251 f(field.expr);
252 }
253 if let Some(expr) = spread {
254 f(*expr);
255 }
256 }
257 Expr::Lambda { body, .. } => {
258 f(*body);
259 }
260 Expr::Field { expr, .. }
261 | Expr::Try { expr }
262 | Expr::Cast { expr, .. }
263 | Expr::Ref { expr, .. }
264 | Expr::UnaryOp { expr, .. } => {
265 f(*expr);
266 }
267 }
268 }
269}
270
143#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 271#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
144pub struct PatId(RawId); 272pub struct PatId(RawId);
145impl_arena_id!(PatId); 273impl_arena_id!(PatId);
146 274
147#[derive(Debug, Clone, Eq, PartialEq)] 275#[derive(Debug, Clone, Eq, PartialEq)]
148pub struct Pat; 276pub enum Pat {
277 Missing,
278 Bind {
279 name: Name,
280 },
281 TupleStruct {
282 path: Option<Path>,
283 args: Vec<PatId>,
284 },
285}
286
287impl Pat {
288 pub fn walk_child_pats(&self, f: impl FnMut(PatId)) {
289 match self {
290 Pat::Missing | Pat::Bind { .. } => {}
291 Pat::TupleStruct { args, .. } => {
292 args.iter().map(|pat| *pat).for_each(f);
293 }
294 }
295 }
296}
149 297
150// Queries 298// Queries
151 299
@@ -163,6 +311,17 @@ struct ExprCollector {
163} 311}
164 312
165impl ExprCollector { 313impl ExprCollector {
314 fn new() -> Self {
315 ExprCollector {
316 exprs: Arena::default(),
317 pats: Arena::default(),
318 expr_syntax_mapping: FxHashMap::default(),
319 expr_syntax_mapping_back: FxHashMap::default(),
320 pat_syntax_mapping: FxHashMap::default(),
321 pat_syntax_mapping_back: FxHashMap::default(),
322 }
323 }
324
166 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: LocalSyntaxPtr) -> ExprId { 325 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: LocalSyntaxPtr) -> ExprId {
167 let id = self.exprs.alloc(expr); 326 let id = self.exprs.alloc(expr);
168 self.expr_syntax_mapping.insert(syntax_ptr, id); 327 self.expr_syntax_mapping.insert(syntax_ptr, id);
@@ -177,30 +336,63 @@ impl ExprCollector {
177 id 336 id
178 } 337 }
179 338
339 fn empty_block(&mut self) -> ExprId {
340 let block = Expr::Block {
341 statements: Vec::new(),
342 tail: None,
343 };
344 self.exprs.alloc(block)
345 }
346
180 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { 347 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
181 let syntax_ptr = LocalSyntaxPtr::new(expr.syntax()); 348 let syntax_ptr = LocalSyntaxPtr::new(expr.syntax());
182 match expr { 349 match expr {
183 ast::Expr::IfExpr(e) => { 350 ast::Expr::IfExpr(e) => {
184 let condition = if let Some(condition) = e.condition() { 351 if let Some(pat) = e.condition().and_then(|c| c.pat()) {
185 if condition.pat().is_none() { 352 // if let -- desugar to match
353 let pat = self.collect_pat(pat);
354 let match_expr =
355 self.collect_expr_opt(e.condition().expect("checked above").expr());
356 let then_branch = self.collect_block_opt(e.then_branch());
357 let else_branch = e
358 .else_branch()
359 .map(|e| self.collect_block(e))
360 .unwrap_or_else(|| self.empty_block());
361 let placeholder_pat = self.pats.alloc(Pat::Missing);
362 let arms = vec![
363 MatchArm {
364 pats: vec![pat],
365 expr: then_branch,
366 },
367 MatchArm {
368 pats: vec![placeholder_pat],
369 expr: else_branch,
370 },
371 ];
372 self.alloc_expr(
373 Expr::Match {
374 expr: match_expr,
375 arms,
376 },
377 syntax_ptr,
378 )
379 } else {
380 let condition = if let Some(condition) = e.condition() {
186 self.collect_expr_opt(condition.expr()) 381 self.collect_expr_opt(condition.expr())
187 } else { 382 } else {
188 // TODO handle if let 383 self.exprs.alloc(Expr::Missing)
189 return self.alloc_expr(Expr::Missing, syntax_ptr); 384 };
190 } 385 let then_branch = self.collect_block_opt(e.then_branch());
191 } else { 386 let else_branch = e.else_branch().map(|e| self.collect_block(e));
192 self.exprs.alloc(Expr::Missing) 387 self.alloc_expr(
193 }; 388 Expr::If {
194 let then_branch = self.collect_block_opt(e.then_branch()); 389 condition,
195 let else_branch = e.else_branch().map(|e| self.collect_block(e)); 390 then_branch,
196 self.alloc_expr( 391 else_branch,
197 Expr::If { 392 },
198 condition, 393 syntax_ptr,
199 then_branch, 394 )
200 else_branch, 395 }
201 },
202 syntax_ptr,
203 )
204 } 396 }
205 ast::Expr::BlockExpr(e) => self.collect_block_opt(e.block()), 397 ast::Expr::BlockExpr(e) => self.collect_block_opt(e.block()),
206 ast::Expr::LoopExpr(e) => { 398 ast::Expr::LoopExpr(e) => {
@@ -368,18 +560,30 @@ impl ExprCollector {
368 let op = e.op(); 560 let op = e.op();
369 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr) 561 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
370 } 562 }
371 563 ast::Expr::LambdaExpr(e) => {
372 // We should never get to these because they're handled in MatchExpr resp. StructLit: 564 let mut args = Vec::new();
373 ast::Expr::MatchArmList(_) | ast::Expr::MatchArm(_) | ast::Expr::MatchGuard(_) => { 565 let mut arg_types = Vec::new();
374 panic!("collect_expr called on {:?}", expr) 566 if let Some(pl) = e.param_list() {
375 } 567 for param in pl.params() {
376 ast::Expr::NamedFieldList(_) | ast::Expr::NamedField(_) => { 568 let pat = self.collect_pat_opt(param.pat());
377 panic!("collect_expr called on {:?}", expr) 569 let type_ref = param.type_ref().map(TypeRef::from_ast);
570 args.push(pat);
571 arg_types.push(type_ref);
572 }
573 }
574 let body = self.collect_expr_opt(e.body());
575 self.alloc_expr(
576 Expr::Lambda {
577 args,
578 arg_types,
579 body,
580 },
581 syntax_ptr,
582 )
378 } 583 }
379 584
380 // TODO implement HIR for these: 585 // TODO implement HIR for these:
381 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 586 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
382 ast::Expr::LambdaExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
383 ast::Expr::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 587 ast::Expr::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
384 ast::Expr::TupleExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 588 ast::Expr::TupleExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
385 ast::Expr::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 589 ast::Expr::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
@@ -431,16 +635,31 @@ impl ExprCollector {
431 635
432 fn collect_pat(&mut self, pat: ast::Pat) -> PatId { 636 fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
433 let syntax_ptr = LocalSyntaxPtr::new(pat.syntax()); 637 let syntax_ptr = LocalSyntaxPtr::new(pat.syntax());
434 // TODO 638 match pat {
435 self.alloc_pat(Pat, syntax_ptr) 639 ast::Pat::BindPat(bp) => {
640 let name = bp
641 .name()
642 .map(|nr| nr.as_name())
643 .unwrap_or_else(Name::missing);
644 self.alloc_pat(Pat::Bind { name }, syntax_ptr)
645 }
646 ast::Pat::TupleStructPat(p) => {
647 let path = p.path().and_then(Path::from_ast);
648 let args = p.args().map(|p| self.collect_pat(p)).collect();
649 self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr)
650 }
651 _ => {
652 // TODO
653 self.alloc_pat(Pat::Missing, syntax_ptr)
654 }
655 }
436 } 656 }
437 657
438 fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId { 658 fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId {
439 if let Some(pat) = pat { 659 if let Some(pat) = pat {
440 self.collect_pat(pat) 660 self.collect_pat(pat)
441 } else { 661 } else {
442 // TODO 662 self.pats.alloc(Pat::Missing)
443 self.pats.alloc(Pat)
444 } 663 }
445 } 664 }
446 665
@@ -461,47 +680,61 @@ impl ExprCollector {
461 } 680 }
462} 681}
463 682
683pub(crate) fn collect_fn_body_syntax(node: ast::FnDef) -> BodySyntaxMapping {
684 let mut collector = ExprCollector::new();
685
686 let args = if let Some(param_list) = node.param_list() {
687 let mut args = Vec::new();
688
689 if let Some(self_param) = param_list.self_param() {
690 let self_param = LocalSyntaxPtr::new(
691 self_param
692 .self_kw()
693 .expect("self param without self keyword")
694 .syntax(),
695 );
696 let arg = collector.alloc_pat(
697 Pat::Bind {
698 name: Name::self_param(),
699 },
700 self_param,
701 );
702 args.push(arg);
703 }
704
705 for param in param_list.params() {
706 let pat = if let Some(pat) = param.pat() {
707 pat
708 } else {
709 continue;
710 };
711 args.push(collector.collect_pat(pat));
712 }
713 args
714 } else {
715 Vec::new()
716 };
717
718 let body = collector.collect_block_opt(node.body());
719 collector.into_body_syntax_mapping(args, body)
720}
721
464pub(crate) fn body_syntax_mapping( 722pub(crate) fn body_syntax_mapping(
465 db: &impl HirDatabase, 723 db: &impl HirDatabase,
466 def_id: DefId, 724 def_id: DefId,
467) -> Cancelable<Arc<BodySyntaxMapping>> { 725) -> Cancelable<Arc<BodySyntaxMapping>> {
468 let def = def_id.resolve(db)?; 726 let def = def_id.resolve(db)?;
469 let mut collector = ExprCollector {
470 exprs: Arena::default(),
471 pats: Arena::default(),
472 expr_syntax_mapping: FxHashMap::default(),
473 expr_syntax_mapping_back: FxHashMap::default(),
474 pat_syntax_mapping: FxHashMap::default(),
475 pat_syntax_mapping_back: FxHashMap::default(),
476 };
477 727
478 let (body, args) = match def { 728 let body_syntax_mapping = match def {
479 Def::Function(f) => { 729 Def::Function(f) => {
480 let node = f.syntax(db); 730 let node = f.syntax(db);
481 let node = node.borrowed(); 731 let node = node.borrowed();
482 732
483 let args = if let Some(param_list) = node.param_list() { 733 collect_fn_body_syntax(node)
484 let mut args = Vec::new();
485 // TODO self param
486 for param in param_list.params() {
487 let pat = if let Some(pat) = param.pat() {
488 pat
489 } else {
490 continue;
491 };
492 args.push(collector.collect_pat(pat));
493 }
494 args
495 } else {
496 Vec::new()
497 };
498
499 let body = collector.collect_block_opt(node.body());
500 (body, args)
501 } 734 }
502 // TODO: consts, etc. 735 // TODO: consts, etc.
503 _ => panic!("Trying to get body for item type without body"), 736 _ => panic!("Trying to get body for item type without body"),
504 }; 737 };
505 738
506 Ok(Arc::new(collector.into_body_syntax_mapping(args, body))) 739 Ok(Arc::new(body_syntax_mapping))
507} 740}
diff --git a/crates/ra_hir/src/function.rs b/crates/ra_hir/src/function.rs
index 75ef308ae..4dbdf81d8 100644
--- a/crates/ra_hir/src/function.rs
+++ b/crates/ra_hir/src/function.rs
@@ -11,9 +11,9 @@ use ra_syntax::{
11 ast::{self, AstNode, DocCommentsOwner, NameOwner}, 11 ast::{self, AstNode, DocCommentsOwner, NameOwner},
12}; 12};
13 13
14use crate::{DefId, DefKind, HirDatabase, ty::InferenceResult, Module, Crate, impl_block::ImplBlock}; 14use crate::{DefId, DefKind, HirDatabase, ty::InferenceResult, Module, Crate, impl_block::ImplBlock, expr::{Body, BodySyntaxMapping}};
15 15
16pub use self::scope::FnScopes; 16pub use self::scope::{FnScopes, ScopesWithSyntaxMapping};
17 17
18#[derive(Debug, Clone, PartialEq, Eq)] 18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct Function { 19pub struct Function {
@@ -36,8 +36,21 @@ impl Function {
36 ast::FnDef::cast(syntax.borrowed()).unwrap().owned() 36 ast::FnDef::cast(syntax.borrowed()).unwrap().owned()
37 } 37 }
38 38
39 pub fn scopes(&self, db: &impl HirDatabase) -> Arc<FnScopes> { 39 pub fn body(&self, db: &impl HirDatabase) -> Cancelable<Arc<Body>> {
40 db.fn_scopes(self.def_id) 40 db.body_hir(self.def_id)
41 }
42
43 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Cancelable<Arc<BodySyntaxMapping>> {
44 db.body_syntax_mapping(self.def_id)
45 }
46
47 pub fn scopes(&self, db: &impl HirDatabase) -> Cancelable<ScopesWithSyntaxMapping> {
48 let scopes = db.fn_scopes(self.def_id)?;
49 let syntax_mapping = db.body_syntax_mapping(self.def_id)?;
50 Ok(ScopesWithSyntaxMapping {
51 scopes,
52 syntax_mapping,
53 })
41 } 54 }
42 55
43 pub fn signature_info(&self, db: &impl HirDatabase) -> Option<FnSignatureInfo> { 56 pub fn signature_info(&self, db: &impl HirDatabase) -> Option<FnSignatureInfo> {
diff --git a/crates/ra_hir/src/function/scope.rs b/crates/ra_hir/src/function/scope.rs
index 42bfe4f32..0607a99cb 100644
--- a/crates/ra_hir/src/function/scope.rs
+++ b/crates/ra_hir/src/function/scope.rs
@@ -1,14 +1,16 @@
1use std::sync::Arc;
2
1use rustc_hash::{FxHashMap, FxHashSet}; 3use rustc_hash::{FxHashMap, FxHashSet};
2 4
3use ra_syntax::{ 5use ra_syntax::{
4 AstNode, SyntaxNodeRef, TextUnit, TextRange, 6 AstNode, SyntaxNodeRef, TextUnit, TextRange,
5 algo::generate, 7 algo::generate,
6 ast::{self, ArgListOwner, LoopBodyOwner, NameOwner}, 8 ast,
7}; 9};
8use ra_arena::{Arena, RawId, impl_arena_id}; 10use ra_arena::{Arena, RawId, impl_arena_id};
9use ra_db::LocalSyntaxPtr; 11use ra_db::LocalSyntaxPtr;
10 12
11use crate::{Name, AsName}; 13use crate::{Name, AsName, expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySyntaxMapping}};
12 14
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub struct ScopeId(RawId); 16pub struct ScopeId(RawId);
@@ -16,15 +18,15 @@ impl_arena_id!(ScopeId);
16 18
17#[derive(Debug, PartialEq, Eq)] 19#[derive(Debug, PartialEq, Eq)]
18pub struct FnScopes { 20pub struct FnScopes {
19 pub self_param: Option<LocalSyntaxPtr>, 21 body: Arc<Body>,
20 scopes: Arena<ScopeId, ScopeData>, 22 scopes: Arena<ScopeId, ScopeData>,
21 scope_for: FxHashMap<LocalSyntaxPtr, ScopeId>, 23 scope_for: FxHashMap<ExprId, ScopeId>,
22} 24}
23 25
24#[derive(Debug, PartialEq, Eq)] 26#[derive(Debug, PartialEq, Eq)]
25pub struct ScopeEntry { 27pub struct ScopeEntry {
26 name: Name, 28 name: Name,
27 ptr: LocalSyntaxPtr, 29 pat: PatId,
28} 30}
29 31
30#[derive(Debug, PartialEq, Eq)] 32#[derive(Debug, PartialEq, Eq)]
@@ -34,28 +36,101 @@ pub struct ScopeData {
34} 36}
35 37
36impl FnScopes { 38impl FnScopes {
37 pub(crate) fn new(fn_def: ast::FnDef) -> FnScopes { 39 pub(crate) fn new(body: Arc<Body>) -> FnScopes {
38 let mut scopes = FnScopes { 40 let mut scopes = FnScopes {
39 self_param: fn_def 41 body: body.clone(),
40 .param_list()
41 .and_then(|it| it.self_param())
42 .map(|it| LocalSyntaxPtr::new(it.syntax())),
43 scopes: Arena::default(), 42 scopes: Arena::default(),
44 scope_for: FxHashMap::default(), 43 scope_for: FxHashMap::default(),
45 }; 44 };
46 let root = scopes.root_scope(); 45 let root = scopes.root_scope();
47 scopes.add_params_bindings(root, fn_def.param_list()); 46 scopes.add_params_bindings(root, body.args());
48 if let Some(body) = fn_def.body() { 47 compute_expr_scopes(body.body_expr(), &body, &mut scopes, root);
49 compute_block_scopes(body, &mut scopes, root)
50 }
51 scopes 48 scopes
52 } 49 }
53 pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { 50 pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
54 &self.scopes[scope].entries 51 &self.scopes[scope].entries
55 } 52 }
53 pub fn scope_chain_for<'a>(&'a self, expr: ExprId) -> impl Iterator<Item = ScopeId> + 'a {
54 generate(self.scope_for(expr), move |&scope| {
55 self.scopes[scope].parent
56 })
57 }
58
59 pub fn resolve_local_name<'a>(
60 &'a self,
61 context_expr: ExprId,
62 name: Name,
63 ) -> Option<&'a ScopeEntry> {
64 let mut shadowed = FxHashSet::default();
65 let ret = self
66 .scope_chain_for(context_expr)
67 .flat_map(|scope| self.entries(scope).iter())
68 .filter(|entry| shadowed.insert(entry.name()))
69 .filter(|entry| entry.name() == &name)
70 .nth(0);
71 ret
72 }
73
74 fn root_scope(&mut self) -> ScopeId {
75 self.scopes.alloc(ScopeData {
76 parent: None,
77 entries: vec![],
78 })
79 }
80 fn new_scope(&mut self, parent: ScopeId) -> ScopeId {
81 self.scopes.alloc(ScopeData {
82 parent: Some(parent),
83 entries: vec![],
84 })
85 }
86 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
87 match body.pat(pat) {
88 Pat::Bind { name } => self.scopes[scope].entries.push(ScopeEntry {
89 name: name.clone(),
90 pat,
91 }),
92 p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)),
93 }
94 }
95 fn add_params_bindings(&mut self, scope: ScopeId, params: &[PatId]) {
96 let body = Arc::clone(&self.body);
97 params
98 .into_iter()
99 .for_each(|it| self.add_bindings(&body, scope, *it));
100 }
101 fn set_scope(&mut self, node: ExprId, scope: ScopeId) {
102 self.scope_for.insert(node, scope);
103 }
104 fn scope_for(&self, expr: ExprId) -> Option<ScopeId> {
105 self.scope_for.get(&expr).map(|&scope| scope)
106 }
107}
108
109#[derive(Debug, Clone, PartialEq, Eq)]
110pub struct ScopesWithSyntaxMapping {
111 pub syntax_mapping: Arc<BodySyntaxMapping>,
112 pub scopes: Arc<FnScopes>,
113}
114
115#[derive(Debug, Clone, PartialEq, Eq)]
116pub struct ScopeEntryWithSyntax {
117 name: Name,
118 ptr: LocalSyntaxPtr,
119}
120
121impl ScopeEntryWithSyntax {
122 pub fn name(&self) -> &Name {
123 &self.name
124 }
125 pub fn ptr(&self) -> LocalSyntaxPtr {
126 self.ptr
127 }
128}
129
130impl ScopesWithSyntaxMapping {
56 pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator<Item = ScopeId> + 'a { 131 pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator<Item = ScopeId> + 'a {
57 generate(self.scope_for(node), move |&scope| { 132 generate(self.scope_for(node), move |&scope| {
58 self.scopes[scope].parent 133 self.scopes.scopes[scope].parent
59 }) 134 })
60 } 135 }
61 pub fn scope_chain_for_offset<'a>( 136 pub fn scope_chain_for_offset<'a>(
@@ -63,26 +138,30 @@ impl FnScopes {
63 offset: TextUnit, 138 offset: TextUnit,
64 ) -> impl Iterator<Item = ScopeId> + 'a { 139 ) -> impl Iterator<Item = ScopeId> + 'a {
65 let scope = self 140 let scope = self
141 .scopes
66 .scope_for 142 .scope_for
67 .iter() 143 .iter()
68 // find containin scope 144 .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope)))
145 // find containing scope
69 .min_by_key(|(ptr, _scope)| { 146 .min_by_key(|(ptr, _scope)| {
70 ( 147 (
71 !(ptr.range().start() <= offset && offset <= ptr.range().end()), 148 !(ptr.range().start() <= offset && offset <= ptr.range().end()),
72 ptr.range().len(), 149 ptr.range().len(),
73 ) 150 )
74 }) 151 })
75 .map(|(ptr, scope)| self.adjust(*ptr, *scope, offset)); 152 .map(|(ptr, scope)| self.adjust(ptr, *scope, offset));
76 153
77 generate(scope, move |&scope| self.scopes[scope].parent) 154 generate(scope, move |&scope| self.scopes.scopes[scope].parent)
78 } 155 }
79 // XXX: during completion, cursor might be outside of any particular 156 // XXX: during completion, cursor might be outside of any particular
80 // expression. Try to figure out the correct scope... 157 // expression. Try to figure out the correct scope...
81 fn adjust(&self, ptr: LocalSyntaxPtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId { 158 fn adjust(&self, ptr: LocalSyntaxPtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId {
82 let r = ptr.range(); 159 let r = ptr.range();
83 let child_scopes = self 160 let child_scopes = self
161 .scopes
84 .scope_for 162 .scope_for
85 .iter() 163 .iter()
164 .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope)))
86 .map(|(ptr, scope)| (ptr.range(), scope)) 165 .map(|(ptr, scope)| (ptr.range(), scope))
87 .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r); 166 .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r);
88 167
@@ -100,22 +179,27 @@ impl FnScopes {
100 .unwrap_or(original_scope) 179 .unwrap_or(original_scope)
101 } 180 }
102 181
103 pub fn resolve_local_name<'a>(&'a self, name_ref: ast::NameRef) -> Option<&'a ScopeEntry> { 182 pub fn resolve_local_name(&self, name_ref: ast::NameRef) -> Option<ScopeEntryWithSyntax> {
104 let mut shadowed = FxHashSet::default(); 183 let mut shadowed = FxHashSet::default();
105 let name = name_ref.as_name(); 184 let name = name_ref.as_name();
106 let ret = self 185 let ret = self
107 .scope_chain(name_ref.syntax()) 186 .scope_chain(name_ref.syntax())
108 .flat_map(|scope| self.entries(scope).iter()) 187 .flat_map(|scope| self.scopes.entries(scope).iter())
109 .filter(|entry| shadowed.insert(entry.name())) 188 .filter(|entry| shadowed.insert(entry.name()))
110 .filter(|entry| entry.name() == &name) 189 .filter(|entry| entry.name() == &name)
111 .nth(0); 190 .nth(0);
112 ret 191 ret.and_then(|entry| {
192 Some(ScopeEntryWithSyntax {
193 name: entry.name().clone(),
194 ptr: self.syntax_mapping.pat_syntax(entry.pat())?,
195 })
196 })
113 } 197 }
114 198
115 pub fn find_all_refs(&self, pat: ast::BindPat) -> Vec<ReferenceDescriptor> { 199 pub fn find_all_refs(&self, pat: ast::BindPat) -> Vec<ReferenceDescriptor> {
116 let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); 200 let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
117 let name_ptr = LocalSyntaxPtr::new(pat.syntax()); 201 let name_ptr = LocalSyntaxPtr::new(pat.syntax());
118 let refs: Vec<_> = fn_def 202 fn_def
119 .syntax() 203 .syntax()
120 .descendants() 204 .descendants()
121 .filter_map(ast::NameRef::cast) 205 .filter_map(ast::NameRef::cast)
@@ -127,203 +211,95 @@ impl FnScopes {
127 name: name_ref.syntax().text().to_string(), 211 name: name_ref.syntax().text().to_string(),
128 range: name_ref.syntax().range(), 212 range: name_ref.syntax().range(),
129 }) 213 })
130 .collect(); 214 .collect()
131
132 refs
133 } 215 }
134 216
135 fn root_scope(&mut self) -> ScopeId {
136 self.scopes.alloc(ScopeData {
137 parent: None,
138 entries: vec![],
139 })
140 }
141 fn new_scope(&mut self, parent: ScopeId) -> ScopeId {
142 self.scopes.alloc(ScopeData {
143 parent: Some(parent),
144 entries: vec![],
145 })
146 }
147 fn add_bindings(&mut self, scope: ScopeId, pat: ast::Pat) {
148 let entries = pat
149 .syntax()
150 .descendants()
151 .filter_map(ast::BindPat::cast)
152 .filter_map(ScopeEntry::new);
153 self.scopes[scope].entries.extend(entries);
154 }
155 fn add_params_bindings(&mut self, scope: ScopeId, params: Option<ast::ParamList>) {
156 params
157 .into_iter()
158 .flat_map(|it| it.params())
159 .filter_map(|it| it.pat())
160 .for_each(|it| self.add_bindings(scope, it));
161 }
162 fn set_scope(&mut self, node: SyntaxNodeRef, scope: ScopeId) {
163 self.scope_for.insert(LocalSyntaxPtr::new(node), scope);
164 }
165 fn scope_for(&self, node: SyntaxNodeRef) -> Option<ScopeId> { 217 fn scope_for(&self, node: SyntaxNodeRef) -> Option<ScopeId> {
166 node.ancestors() 218 node.ancestors()
167 .map(LocalSyntaxPtr::new) 219 .map(LocalSyntaxPtr::new)
168 .filter_map(|it| self.scope_for.get(&it).map(|&scope| scope)) 220 .filter_map(|ptr| self.syntax_mapping.syntax_expr(ptr))
221 .filter_map(|it| self.scopes.scope_for(it))
169 .next() 222 .next()
170 } 223 }
171} 224}
172 225
173impl ScopeEntry { 226impl ScopeEntry {
174 fn new(pat: ast::BindPat) -> Option<ScopeEntry> {
175 let name = pat.name()?.as_name();
176 let res = ScopeEntry {
177 name,
178 ptr: LocalSyntaxPtr::new(pat.syntax()),
179 };
180 Some(res)
181 }
182 pub fn name(&self) -> &Name { 227 pub fn name(&self) -> &Name {
183 &self.name 228 &self.name
184 } 229 }
185 pub fn ptr(&self) -> LocalSyntaxPtr { 230 pub fn pat(&self) -> PatId {
186 self.ptr 231 self.pat
187 } 232 }
188} 233}
189 234
190fn compute_block_scopes(block: ast::Block, scopes: &mut FnScopes, mut scope: ScopeId) { 235fn compute_block_scopes(
191 // A hack for completion :( 236 statements: &[Statement],
192 scopes.set_scope(block.syntax(), scope); 237 tail: Option<ExprId>,
193 for stmt in block.statements() { 238 body: &Body,
239 scopes: &mut FnScopes,
240 mut scope: ScopeId,
241) {
242 for stmt in statements {
194 match stmt { 243 match stmt {
195 ast::Stmt::LetStmt(stmt) => { 244 Statement::Let {
196 if let Some(expr) = stmt.initializer() { 245 pat, initializer, ..
197 scopes.set_scope(expr.syntax(), scope); 246 } => {
198 compute_expr_scopes(expr, scopes, scope); 247 if let Some(expr) = initializer {
248 scopes.set_scope(*expr, scope);
249 compute_expr_scopes(*expr, body, scopes, scope);
199 } 250 }
200 scope = scopes.new_scope(scope); 251 scope = scopes.new_scope(scope);
201 if let Some(pat) = stmt.pat() { 252 scopes.add_bindings(body, scope, *pat);
202 scopes.add_bindings(scope, pat);
203 }
204 } 253 }
205 ast::Stmt::ExprStmt(expr_stmt) => { 254 Statement::Expr(expr) => {
206 if let Some(expr) = expr_stmt.expr() { 255 scopes.set_scope(*expr, scope);
207 scopes.set_scope(expr.syntax(), scope); 256 compute_expr_scopes(*expr, body, scopes, scope);
208 compute_expr_scopes(expr, scopes, scope);
209 }
210 } 257 }
211 } 258 }
212 } 259 }
213 if let Some(expr) = block.expr() { 260 if let Some(expr) = tail {
214 scopes.set_scope(expr.syntax(), scope); 261 compute_expr_scopes(expr, body, scopes, scope);
215 compute_expr_scopes(expr, scopes, scope);
216 } 262 }
217} 263}
218 264
219fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { 265fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut FnScopes, scope: ScopeId) {
220 match expr { 266 scopes.set_scope(expr, scope);
221 ast::Expr::IfExpr(e) => { 267 match body.expr(expr) {
222 let cond_scope = e 268 Expr::Block { statements, tail } => {
223 .condition() 269 compute_block_scopes(&statements, *tail, body, scopes, scope);
224 .and_then(|cond| compute_cond_scopes(cond, scopes, scope));
225 if let Some(block) = e.then_branch() {
226 compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope));
227 }
228 if let Some(block) = e.else_branch() {
229 compute_block_scopes(block, scopes, scope);
230 }
231 }
232 ast::Expr::BlockExpr(e) => {
233 if let Some(block) = e.block() {
234 compute_block_scopes(block, scopes, scope);
235 }
236 }
237 ast::Expr::LoopExpr(e) => {
238 if let Some(block) = e.loop_body() {
239 compute_block_scopes(block, scopes, scope);
240 }
241 }
242 ast::Expr::WhileExpr(e) => {
243 let cond_scope = e
244 .condition()
245 .and_then(|cond| compute_cond_scopes(cond, scopes, scope));
246 if let Some(block) = e.loop_body() {
247 compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope));
248 }
249 } 270 }
250 ast::Expr::ForExpr(e) => { 271 Expr::For {
251 if let Some(expr) = e.iterable() { 272 iterable,
252 compute_expr_scopes(expr, scopes, scope); 273 pat,
253 } 274 body: body_expr,
254 let mut scope = scope; 275 } => {
255 if let Some(pat) = e.pat() { 276 compute_expr_scopes(*iterable, body, scopes, scope);
256 scope = scopes.new_scope(scope);
257 scopes.add_bindings(scope, pat);
258 }
259 if let Some(block) = e.loop_body() {
260 compute_block_scopes(block, scopes, scope);
261 }
262 }
263 ast::Expr::LambdaExpr(e) => {
264 let scope = scopes.new_scope(scope); 277 let scope = scopes.new_scope(scope);
265 scopes.add_params_bindings(scope, e.param_list()); 278 scopes.add_bindings(body, scope, *pat);
266 if let Some(body) = e.body() { 279 compute_expr_scopes(*body_expr, body, scopes, scope);
267 scopes.set_scope(body.syntax(), scope);
268 compute_expr_scopes(body, scopes, scope);
269 }
270 } 280 }
271 ast::Expr::CallExpr(e) => { 281 Expr::Lambda {
272 compute_call_scopes(e.expr(), e.arg_list(), scopes, scope); 282 args,
273 } 283 body: body_expr,
274 ast::Expr::MethodCallExpr(e) => { 284 ..
275 compute_call_scopes(e.expr(), e.arg_list(), scopes, scope); 285 } => {
286 let scope = scopes.new_scope(scope);
287 scopes.add_params_bindings(scope, &args);
288 compute_expr_scopes(*body_expr, body, scopes, scope);
276 } 289 }
277 ast::Expr::MatchExpr(e) => { 290 Expr::Match { expr, arms } => {
278 if let Some(expr) = e.expr() { 291 compute_expr_scopes(*expr, body, scopes, scope);
279 compute_expr_scopes(expr, scopes, scope); 292 for arm in arms {
280 }
281 for arm in e.match_arm_list().into_iter().flat_map(|it| it.arms()) {
282 let scope = scopes.new_scope(scope); 293 let scope = scopes.new_scope(scope);
283 for pat in arm.pats() { 294 for pat in &arm.pats {
284 scopes.add_bindings(scope, pat); 295 scopes.add_bindings(body, scope, *pat);
285 }
286 if let Some(expr) = arm.expr() {
287 compute_expr_scopes(expr, scopes, scope);
288 } 296 }
297 scopes.set_scope(arm.expr, scope);
298 compute_expr_scopes(arm.expr, body, scopes, scope);
289 } 299 }
290 } 300 }
291 _ => expr 301 e => e.walk_child_exprs(|e| compute_expr_scopes(e, body, scopes, scope)),
292 .syntax()
293 .children()
294 .filter_map(ast::Expr::cast)
295 .for_each(|expr| compute_expr_scopes(expr, scopes, scope)),
296 }; 302 };
297
298 fn compute_call_scopes(
299 receiver: Option<ast::Expr>,
300 arg_list: Option<ast::ArgList>,
301 scopes: &mut FnScopes,
302 scope: ScopeId,
303 ) {
304 arg_list
305 .into_iter()
306 .flat_map(|it| it.args())
307 .chain(receiver)
308 .for_each(|expr| compute_expr_scopes(expr, scopes, scope));
309 }
310
311 fn compute_cond_scopes(
312 cond: ast::Condition,
313 scopes: &mut FnScopes,
314 scope: ScopeId,
315 ) -> Option<ScopeId> {
316 if let Some(expr) = cond.expr() {
317 compute_expr_scopes(expr, scopes, scope);
318 }
319 if let Some(pat) = cond.pat() {
320 let s = scopes.new_scope(scope);
321 scopes.add_bindings(s, pat);
322 Some(s)
323 } else {
324 None
325 }
326 }
327} 303}
328 304
329#[derive(Debug)] 305#[derive(Debug)]
@@ -338,6 +314,8 @@ mod tests {
338 use ra_syntax::SourceFileNode; 314 use ra_syntax::SourceFileNode;
339 use test_utils::{extract_offset, assert_eq_text}; 315 use test_utils::{extract_offset, assert_eq_text};
340 316
317 use crate::expr;
318
341 use super::*; 319 use super::*;
342 320
343 fn do_check(code: &str, expected: &[&str]) { 321 fn do_check(code: &str, expected: &[&str]) {
@@ -353,15 +331,20 @@ mod tests {
353 let file = SourceFileNode::parse(&code); 331 let file = SourceFileNode::parse(&code);
354 let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); 332 let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
355 let fn_def: ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 333 let fn_def: ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
356 let scopes = FnScopes::new(fn_def); 334 let body_hir = expr::collect_fn_body_syntax(fn_def);
335 let scopes = FnScopes::new(Arc::clone(body_hir.body()));
336 let scopes = ScopesWithSyntaxMapping {
337 scopes: Arc::new(scopes),
338 syntax_mapping: Arc::new(body_hir),
339 };
357 let actual = scopes 340 let actual = scopes
358 .scope_chain(marker.syntax()) 341 .scope_chain(marker.syntax())
359 .flat_map(|scope| scopes.entries(scope)) 342 .flat_map(|scope| scopes.scopes.entries(scope))
360 .map(|it| it.name().to_string()) 343 .map(|it| it.name().to_string())
361 .collect::<Vec<_>>() 344 .collect::<Vec<_>>()
362 .join("\n"); 345 .join("\n");
363 let expected = expected.join("\n"); 346 let expected = expected.join("\n");
364 assert_eq_text!(&actual, &expected); 347 assert_eq_text!(&expected, &actual);
365 } 348 }
366 349
367 #[test] 350 #[test]
@@ -389,7 +372,7 @@ mod tests {
389 } 372 }
390 373
391 #[test] 374 #[test]
392 fn test_metod_call_scope() { 375 fn test_method_call_scope() {
393 do_check( 376 do_check(
394 r" 377 r"
395 fn quux() { 378 fn quux() {
@@ -445,10 +428,15 @@ mod tests {
445 let fn_def: ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 428 let fn_def: ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
446 let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); 429 let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
447 430
448 let scopes = FnScopes::new(fn_def); 431 let body_hir = expr::collect_fn_body_syntax(fn_def);
432 let scopes = FnScopes::new(Arc::clone(body_hir.body()));
433 let scopes = ScopesWithSyntaxMapping {
434 scopes: Arc::new(scopes),
435 syntax_mapping: Arc::new(body_hir),
436 };
449 437
450 let local_name_entry = scopes.resolve_local_name(name_ref).unwrap(); 438 let local_name_entry = scopes.resolve_local_name(name_ref).unwrap();
451 let local_name = local_name_entry.ptr().resolve(&file); 439 let local_name = local_name_entry.ptr();
452 let expected_name = 440 let expected_name =
453 find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()).unwrap(); 441 find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()).unwrap();
454 assert_eq!(local_name.range(), expected_name.syntax().range()); 442 assert_eq!(local_name.range(), expected_name.syntax().range());
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index fea9e141b..82dc287de 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -47,7 +47,7 @@ pub use self::{
47 ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc}, 47 ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc},
48 macros::{MacroDef, MacroInput, MacroExpansion}, 48 macros::{MacroDef, MacroInput, MacroExpansion},
49 module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, 49 module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution},
50 function::{Function, FnScopes}, 50 function::{Function, FnScopes, ScopesWithSyntaxMapping},
51 adt::{Struct, Enum}, 51 adt::{Struct, Enum},
52 ty::Ty, 52 ty::Ty,
53 impl_block::{ImplBlock, ImplItem}, 53 impl_block::{ImplBlock, ImplItem},
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index 017caf442..6f95b168f 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -31,6 +31,10 @@ impl Name {
31 Name::new("[missing name]".into()) 31 Name::new("[missing name]".into())
32 } 32 }
33 33
34 pub(crate) fn self_param() -> Name {
35 Name::new("self".into())
36 }
37
34 pub(crate) fn tuple_field_name(idx: usize) -> Name { 38 pub(crate) fn tuple_field_name(idx: usize) -> Name {
35 Name::new(idx.to_string().into()) 39 Name::new(idx.to_string().into())
36 } 40 }
@@ -51,7 +55,8 @@ impl Name {
51 "u128" => KnownName::U128, 55 "u128" => KnownName::U128,
52 "f32" => KnownName::F32, 56 "f32" => KnownName::F32,
53 "f64" => KnownName::F64, 57 "f64" => KnownName::F64,
54 "Self" => KnownName::Self_, 58 "Self" => KnownName::SelfType,
59 "self" => KnownName::SelfParam,
55 _ => return None, 60 _ => return None,
56 }; 61 };
57 Some(name) 62 Some(name)
@@ -104,5 +109,6 @@ pub(crate) enum KnownName {
104 F32, 109 F32,
105 F64, 110 F64,
106 111
107 Self_, 112 SelfType,
113 SelfParam,
108} 114}
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index a5d99beda..d9ee9d37f 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
11use ra_db::{SourceRootId, Cancelable,}; 11use ra_db::{SourceRootId, Cancelable,};
12 12
13use crate::{ 13use crate::{
14 SourceFileItems, SourceItemId, DefKind, Function, DefId, Name, AsName, HirFileId, 14 SourceFileItems, SourceItemId, DefKind, DefId, Name, AsName, HirFileId,
15 MacroCallLoc, 15 MacroCallLoc,
16 db::HirDatabase, 16 db::HirDatabase,
17 function::FnScopes, 17 function::FnScopes,
@@ -23,11 +23,10 @@ use crate::{
23 adt::{StructData, EnumData}, 23 adt::{StructData, EnumData},
24}; 24};
25 25
26pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc<FnScopes> { 26pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<FnScopes>> {
27 let function = Function::new(def_id); 27 let body = db.body_hir(def_id)?;
28 let syntax = function.syntax(db); 28 let res = FnScopes::new(body);
29 let res = FnScopes::new(syntax.borrowed()); 29 Ok(Arc::new(res))
30 Arc::new(res)
31} 30}
32 31
33pub(super) fn struct_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<StructData>> { 32pub(super) fn struct_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<StructData>> {
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index e33762e0d..8c320a705 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -31,10 +31,11 @@ use ra_syntax::{
31}; 31};
32 32
33use crate::{ 33use crate::{
34 Def, DefId, FnScopes, Module, Function, Struct, Enum, Path, Name, AsName, ImplBlock, 34 Def, DefId, Module, Function, Struct, Enum, Path, Name, AsName, ImplBlock,
35 db::HirDatabase, 35 db::HirDatabase,
36 type_ref::{TypeRef, Mutability}, 36 type_ref::{TypeRef, Mutability},
37 name::KnownName, 37 name::KnownName,
38 ScopesWithSyntaxMapping,
38}; 39};
39 40
40/// The ID of a type variable. 41/// The ID of a type variable.
@@ -305,7 +306,7 @@ impl Ty {
305 return Ok(Ty::Uint(uint_ty)); 306 return Ok(Ty::Uint(uint_ty));
306 } else if let Some(float_ty) = primitive::FloatTy::from_name(name) { 307 } else if let Some(float_ty) = primitive::FloatTy::from_name(name) {
307 return Ok(Ty::Float(float_ty)); 308 return Ok(Ty::Float(float_ty));
308 } else if name.as_known_name() == Some(KnownName::Self_) { 309 } else if name.as_known_name() == Some(KnownName::SelfType) {
309 return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type())); 310 return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type()));
310 } 311 }
311 } 312 }
@@ -515,7 +516,7 @@ impl InferenceResult {
515#[derive(Clone, Debug)] 516#[derive(Clone, Debug)]
516struct InferenceContext<'a, D: HirDatabase> { 517struct InferenceContext<'a, D: HirDatabase> {
517 db: &'a D, 518 db: &'a D,
518 scopes: Arc<FnScopes>, 519 scopes: ScopesWithSyntaxMapping,
519 /// The self param for the current method, if it exists. 520 /// The self param for the current method, if it exists.
520 self_param: Option<LocalSyntaxPtr>, 521 self_param: Option<LocalSyntaxPtr>,
521 module: Module, 522 module: Module,
@@ -529,7 +530,7 @@ struct InferenceContext<'a, D: HirDatabase> {
529impl<'a, D: HirDatabase> InferenceContext<'a, D> { 530impl<'a, D: HirDatabase> InferenceContext<'a, D> {
530 fn new( 531 fn new(
531 db: &'a D, 532 db: &'a D,
532 scopes: Arc<FnScopes>, 533 scopes: ScopesWithSyntaxMapping,
533 module: Module, 534 module: Module,
534 impl_block: Option<ImplBlock>, 535 impl_block: Option<ImplBlock>,
535 ) -> Self { 536 ) -> Self {
@@ -826,10 +827,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
826 self.infer_expr_opt(e.expr(), &Expectation::none())?; 827 self.infer_expr_opt(e.expr(), &Expectation::none())?;
827 Ty::Never 828 Ty::Never
828 } 829 }
829 ast::Expr::MatchArmList(_) | ast::Expr::MatchArm(_) | ast::Expr::MatchGuard(_) => {
830 // Can this even occur outside of a match expression?
831 Ty::Unknown
832 }
833 ast::Expr::StructLit(e) => { 830 ast::Expr::StructLit(e) => {
834 let (ty, def_id) = self.resolve_variant(e.path())?; 831 let (ty, def_id) = self.resolve_variant(e.path())?;
835 if let Some(nfl) = e.named_field_list() { 832 if let Some(nfl) = e.named_field_list() {
@@ -845,10 +842,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
845 } 842 }
846 ty 843 ty
847 } 844 }
848 ast::Expr::NamedFieldList(_) | ast::Expr::NamedField(_) => {
849 // Can this even occur outside of a struct literal?
850 Ty::Unknown
851 }
852 ast::Expr::IndexExpr(_e) => Ty::Unknown, 845 ast::Expr::IndexExpr(_e) => Ty::Unknown,
853 ast::Expr::FieldExpr(e) => { 846 ast::Expr::FieldExpr(e) => {
854 let receiver_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?; 847 let receiver_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?;
@@ -1016,7 +1009,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1016 1009
1017pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> { 1010pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> {
1018 let function = Function::new(def_id); // TODO: consts also need inference 1011 let function = Function::new(def_id); // TODO: consts also need inference
1019 let scopes = function.scopes(db); 1012 let scopes = function.scopes(db)?;
1020 let module = function.module(db)?; 1013 let module = function.module(db)?;
1021 let impl_block = function.impl_block(db)?; 1014 let impl_block = function.impl_block(db)?;
1022 let mut ctx = InferenceContext::new(db, scopes, module, impl_block); 1015 let mut ctx = InferenceContext::new(db, scopes, module, impl_block);
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index deb4dea88..24f72393a 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -927,12 +927,7 @@ pub enum Expr<'a> {
927 BlockExpr(BlockExpr<'a>), 927 BlockExpr(BlockExpr<'a>),
928 ReturnExpr(ReturnExpr<'a>), 928 ReturnExpr(ReturnExpr<'a>),
929 MatchExpr(MatchExpr<'a>), 929 MatchExpr(MatchExpr<'a>),
930 MatchArmList(MatchArmList<'a>),
931 MatchArm(MatchArm<'a>),
932 MatchGuard(MatchGuard<'a>),
933 StructLit(StructLit<'a>), 930 StructLit(StructLit<'a>),
934 NamedFieldList(NamedFieldList<'a>),
935 NamedField(NamedField<'a>),
936 CallExpr(CallExpr<'a>), 931 CallExpr(CallExpr<'a>),
937 IndexExpr(IndexExpr<'a>), 932 IndexExpr(IndexExpr<'a>),
938 MethodCallExpr(MethodCallExpr<'a>), 933 MethodCallExpr(MethodCallExpr<'a>),
@@ -964,12 +959,7 @@ impl<'a> AstNode<'a> for Expr<'a> {
964 BLOCK_EXPR => Some(Expr::BlockExpr(BlockExpr { syntax })), 959 BLOCK_EXPR => Some(Expr::BlockExpr(BlockExpr { syntax })),
965 RETURN_EXPR => Some(Expr::ReturnExpr(ReturnExpr { syntax })), 960 RETURN_EXPR => Some(Expr::ReturnExpr(ReturnExpr { syntax })),
966 MATCH_EXPR => Some(Expr::MatchExpr(MatchExpr { syntax })), 961 MATCH_EXPR => Some(Expr::MatchExpr(MatchExpr { syntax })),
967 MATCH_ARM_LIST => Some(Expr::MatchArmList(MatchArmList { syntax })),
968 MATCH_ARM => Some(Expr::MatchArm(MatchArm { syntax })),
969 MATCH_GUARD => Some(Expr::MatchGuard(MatchGuard { syntax })),
970 STRUCT_LIT => Some(Expr::StructLit(StructLit { syntax })), 962 STRUCT_LIT => Some(Expr::StructLit(StructLit { syntax })),
971 NAMED_FIELD_LIST => Some(Expr::NamedFieldList(NamedFieldList { syntax })),
972 NAMED_FIELD => Some(Expr::NamedField(NamedField { syntax })),
973 CALL_EXPR => Some(Expr::CallExpr(CallExpr { syntax })), 963 CALL_EXPR => Some(Expr::CallExpr(CallExpr { syntax })),
974 INDEX_EXPR => Some(Expr::IndexExpr(IndexExpr { syntax })), 964 INDEX_EXPR => Some(Expr::IndexExpr(IndexExpr { syntax })),
975 METHOD_CALL_EXPR => Some(Expr::MethodCallExpr(MethodCallExpr { syntax })), 965 METHOD_CALL_EXPR => Some(Expr::MethodCallExpr(MethodCallExpr { syntax })),
@@ -1001,12 +991,7 @@ impl<'a> AstNode<'a> for Expr<'a> {
1001 Expr::BlockExpr(inner) => inner.syntax(), 991 Expr::BlockExpr(inner) => inner.syntax(),
1002 Expr::ReturnExpr(inner) => inner.syntax(), 992 Expr::ReturnExpr(inner) => inner.syntax(),
1003 Expr::MatchExpr(inner) => inner.syntax(), 993 Expr::MatchExpr(inner) => inner.syntax(),
1004 Expr::MatchArmList(inner) => inner.syntax(),
1005 Expr::MatchArm(inner) => inner.syntax(),
1006 Expr::MatchGuard(inner) => inner.syntax(),
1007 Expr::StructLit(inner) => inner.syntax(), 994 Expr::StructLit(inner) => inner.syntax(),
1008 Expr::NamedFieldList(inner) => inner.syntax(),
1009 Expr::NamedField(inner) => inner.syntax(),
1010 Expr::CallExpr(inner) => inner.syntax(), 995 Expr::CallExpr(inner) => inner.syntax(),
1011 Expr::IndexExpr(inner) => inner.syntax(), 996 Expr::IndexExpr(inner) => inner.syntax(),
1012 Expr::MethodCallExpr(inner) => inner.syntax(), 997 Expr::MethodCallExpr(inner) => inner.syntax(),
@@ -4155,7 +4140,15 @@ impl<R: TreeRoot<RaTypes>> TupleStructPatNode<R> {
4155} 4140}
4156 4141
4157 4142
4158impl<'a> TupleStructPat<'a> {} 4143impl<'a> TupleStructPat<'a> {
4144 pub fn args(self) -> impl Iterator<Item = Pat<'a>> + 'a {
4145 super::children(self)
4146 }
4147
4148 pub fn path(self) -> Option<Path<'a>> {
4149 super::child_opt(self)
4150 }
4151}
4159 4152
4160// TupleType 4153// TupleType
4161#[derive(Debug, Clone, Copy,)] 4154#[derive(Debug, Clone, Copy,)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 5bcdf3f1d..3c640ed47 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -446,12 +446,7 @@ Grammar(
446 "BlockExpr", 446 "BlockExpr",
447 "ReturnExpr", 447 "ReturnExpr",
448 "MatchExpr", 448 "MatchExpr",
449 "MatchArmList",
450 "MatchArm",
451 "MatchGuard",
452 "StructLit", 449 "StructLit",
453 "NamedFieldList",
454 "NamedField",
455 "CallExpr", 450 "CallExpr",
456 "IndexExpr", 451 "IndexExpr",
457 "MethodCallExpr", 452 "MethodCallExpr",
@@ -472,7 +467,10 @@ Grammar(
472 "PathPat": (), 467 "PathPat": (),
473 "StructPat": (), 468 "StructPat": (),
474 "FieldPatList": (), 469 "FieldPatList": (),
475 "TupleStructPat": (), 470 "TupleStructPat": (
471 options: ["Path"],
472 collections: [["args", "Pat"]],
473 ),
476 "TuplePat": (), 474 "TuplePat": (),
477 "SlicePat": (), 475 "SlicePat": (),
478 "RangePat": (), 476 "RangePat": (),