diff options
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 5 | ||||
-rw-r--r-- | crates/ra_ide/src/goto_definition.rs | 10 | ||||
-rw-r--r-- | crates/ra_ide/src/goto_type_definition.rs | 23 |
5 files changed, 51 insertions, 8 deletions
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 3d78f71c1..6b6c5e494 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -192,6 +192,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
192 | self.imp.type_of_pat(pat) | 192 | self.imp.type_of_pat(pat) |
193 | } | 193 | } |
194 | 194 | ||
195 | pub fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { | ||
196 | self.imp.type_of_self(param) | ||
197 | } | ||
198 | |||
195 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | 199 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { |
196 | self.imp.resolve_method_call(call) | 200 | self.imp.resolve_method_call(call) |
197 | } | 201 | } |
@@ -216,6 +220,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
216 | self.imp.resolve_path(path) | 220 | self.imp.resolve_path(path) |
217 | } | 221 | } |
218 | 222 | ||
223 | // TODO: id | ||
219 | pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> { | 224 | pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> { |
220 | self.imp.resolve_variant(record_lit) | 225 | self.imp.resolve_variant(record_lit) |
221 | } | 226 | } |
@@ -377,6 +382,10 @@ impl<'db> SemanticsImpl<'db> { | |||
377 | self.analyze(pat.syntax()).type_of_pat(self.db, &pat) | 382 | self.analyze(pat.syntax()).type_of_pat(self.db, &pat) |
378 | } | 383 | } |
379 | 384 | ||
385 | pub fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { | ||
386 | self.analyze(param.syntax()).type_of_self(self.db, ¶m) | ||
387 | } | ||
388 | |||
380 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | 389 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { |
381 | self.analyze(call.syntax()).resolve_method_call(self.db, call) | 390 | self.analyze(call.syntax()).resolve_method_call(self.db, call) |
382 | } | 391 | } |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 1d6c47103..1f1bdc0d8 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -115,6 +115,7 @@ impl SourceAnalyzer { | |||
115 | Some(res) | 115 | Some(res) |
116 | } | 116 | } |
117 | 117 | ||
118 | // TODO: rename | ||
118 | pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { | 119 | pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { |
119 | let expr_id = self.expr_id(db, expr)?; | 120 | let expr_id = self.expr_id(db, expr)?; |
120 | let ty = self.infer.as_ref()?[expr_id].clone(); | 121 | let ty = self.infer.as_ref()?[expr_id].clone(); |
@@ -127,6 +128,17 @@ impl SourceAnalyzer { | |||
127 | Type::new_with_resolver(db, &self.resolver, ty) | 128 | Type::new_with_resolver(db, &self.resolver, ty) |
128 | } | 129 | } |
129 | 130 | ||
131 | pub(crate) fn type_of_self( | ||
132 | &self, | ||
133 | db: &dyn HirDatabase, | ||
134 | param: &ast::SelfParam, | ||
135 | ) -> Option<Type> { | ||
136 | let src = InFile { file_id: self.file_id, value: param }; | ||
137 | let pat_id = self.body_source_map.as_ref()?.node_self_param(src)?; | ||
138 | let ty = self.infer.as_ref()?[pat_id].clone(); | ||
139 | Type::new_with_resolver(db, &self.resolver, ty) | ||
140 | } | ||
141 | |||
130 | pub(crate) fn resolve_method_call( | 142 | pub(crate) fn resolve_method_call( |
131 | &self, | 143 | &self, |
132 | db: &dyn HirDatabase, | 144 | db: &dyn HirDatabase, |
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 4f2350915..031ffe13f 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -302,6 +302,11 @@ impl BodySourceMap { | |||
302 | self.pat_map.get(&src).cloned() | 302 | self.pat_map.get(&src).cloned() |
303 | } | 303 | } |
304 | 304 | ||
305 | pub fn node_self_param(&self, node: InFile<&ast::SelfParam>) -> Option<PatId> { | ||
306 | let src = node.map(|it| Either::Right(AstPtr::new(it))); | ||
307 | self.pat_map.get(&src).cloned() | ||
308 | } | ||
309 | |||
305 | pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordField>> { | 310 | pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordField>> { |
306 | self.field_map[&(expr, field)].clone() | 311 | self.field_map[&(expr, field)].clone() |
307 | } | 312 | } |
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 4c78fa214..8fc33d031 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs | |||
@@ -7,7 +7,7 @@ use ra_syntax::{ | |||
7 | ast::{self}, | 7 | ast::{self}, |
8 | match_ast, AstNode, | 8 | match_ast, AstNode, |
9 | SyntaxKind::*, | 9 | SyntaxKind::*, |
10 | SyntaxToken, TokenAtOffset, | 10 | SyntaxToken, TokenAtOffset, T, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
@@ -32,9 +32,10 @@ pub(crate) fn goto_definition( | |||
32 | let file = sema.parse(position.file_id).syntax().clone(); | 32 | let file = sema.parse(position.file_id).syntax().clone(); |
33 | let original_token = pick_best(file.token_at_offset(position.offset))?; | 33 | let original_token = pick_best(file.token_at_offset(position.offset))?; |
34 | let token = sema.descend_into_macros(original_token.clone()); | 34 | let token = sema.descend_into_macros(original_token.clone()); |
35 | let parent = token.parent(); | ||
35 | 36 | ||
36 | let nav_targets = match_ast! { | 37 | let nav_targets = match_ast! { |
37 | match (token.parent()) { | 38 | match parent { |
38 | ast::NameRef(name_ref) => { | 39 | ast::NameRef(name_ref) => { |
39 | reference_definition(&sema, &name_ref).to_vec() | 40 | reference_definition(&sema, &name_ref).to_vec() |
40 | }, | 41 | }, |
@@ -57,7 +58,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | |||
57 | return tokens.max_by_key(priority); | 58 | return tokens.max_by_key(priority); |
58 | fn priority(n: &SyntaxToken) -> usize { | 59 | fn priority(n: &SyntaxToken) -> usize { |
59 | match n.kind() { | 60 | match n.kind() { |
60 | IDENT | INT_NUMBER => 2, | 61 | IDENT | INT_NUMBER | T![self] => 2, |
61 | kind if kind.is_trivia() => 0, | 62 | kind if kind.is_trivia() => 0, |
62 | _ => 1, | 63 | _ => 1, |
63 | } | 64 | } |
@@ -121,7 +122,8 @@ mod tests { | |||
121 | data => panic!("bad data: {}", data), | 122 | data => panic!("bad data: {}", data), |
122 | } | 123 | } |
123 | 124 | ||
124 | let mut navs = analysis.goto_definition(position).unwrap().unwrap().info; | 125 | let mut navs = |
126 | analysis.goto_definition(position).unwrap().expect("no definition found").info; | ||
125 | if navs.len() == 0 { | 127 | if navs.len() == 0 { |
126 | panic!("unresolved reference") | 128 | panic!("unresolved reference") |
127 | } | 129 | } |
diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index 7eb40d637..d9cf975d4 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use ra_ide_db::RootDatabase; | 1 | use ra_ide_db::RootDatabase; |
2 | use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; | 2 | use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; |
3 | 3 | ||
4 | use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; | 4 | use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; |
5 | 5 | ||
@@ -25,8 +25,9 @@ pub(crate) fn goto_type_definition( | |||
25 | let (ty, node) = sema.ancestors_with_macros(token.parent()).find_map(|node| { | 25 | let (ty, node) = sema.ancestors_with_macros(token.parent()).find_map(|node| { |
26 | let ty = match_ast! { | 26 | let ty = match_ast! { |
27 | match node { | 27 | match node { |
28 | ast::Expr(expr) => sema.type_of_expr(&expr)?, | 28 | ast::Expr(it) => sema.type_of_expr(&it)?, |
29 | ast::Pat(pat) => sema.type_of_pat(&pat)?, | 29 | ast::Pat(it) => sema.type_of_pat(&it)?, |
30 | ast::SelfParam(it) => sema.type_of_self(&it)?, | ||
30 | _ => return None, | 31 | _ => return None, |
31 | } | 32 | } |
32 | }; | 33 | }; |
@@ -44,7 +45,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | |||
44 | return tokens.max_by_key(priority); | 45 | return tokens.max_by_key(priority); |
45 | fn priority(n: &SyntaxToken) -> usize { | 46 | fn priority(n: &SyntaxToken) -> usize { |
46 | match n.kind() { | 47 | match n.kind() { |
47 | IDENT | INT_NUMBER => 2, | 48 | IDENT | INT_NUMBER | T![self] => 2, |
48 | kind if kind.is_trivia() => 0, | 49 | kind if kind.is_trivia() => 0, |
49 | _ => 1, | 50 | _ => 1, |
50 | } | 51 | } |
@@ -140,4 +141,18 @@ mod tests { | |||
140 | "Foo STRUCT_DEF FileId(1) 0..11 7..10", | 141 | "Foo STRUCT_DEF FileId(1) 0..11 7..10", |
141 | ); | 142 | ); |
142 | } | 143 | } |
144 | |||
145 | #[test] | ||
146 | fn goto_def_for_self_param() { | ||
147 | check_goto( | ||
148 | r#" | ||
149 | struct Foo; | ||
150 | impl Foo { | ||
151 | //^^^ | ||
152 | fn f(&self<|>) {} | ||
153 | } | ||
154 | "#, | ||
155 | "Foo STRUCT_DEF FileId(1) 0..11 7..10", | ||
156 | ) | ||
157 | } | ||
143 | } | 158 | } |