aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/semantics.rs9
-rw-r--r--crates/ra_hir/src/source_analyzer.rs12
-rw-r--r--crates/ra_hir_def/src/body.rs5
-rw-r--r--crates/ra_ide/src/goto_definition.rs10
-rw-r--r--crates/ra_ide/src/goto_type_definition.rs23
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, &param)
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
13use crate::{ 13use 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 @@
1use ra_ide_db::RootDatabase; 1use ra_ide_db::RootDatabase;
2use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; 2use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
3 3
4use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; 4use 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#"
149struct Foo;
150impl Foo {
151 //^^^
152 fn f(&self<|>) {}
153}
154"#,
155 "Foo STRUCT_DEF FileId(1) 0..11 7..10",
156 )
157 }
143} 158}