From b85042601d69d1c592b731430ef0e445c39fda56 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Jul 2020 14:08:35 +0200 Subject: Goto type definition works for self --- crates/ra_hir/src/semantics.rs | 9 +++++++++ crates/ra_hir/src/source_analyzer.rs | 12 ++++++++++++ crates/ra_hir_def/src/body.rs | 5 +++++ crates/ra_ide/src/goto_definition.rs | 10 ++++++---- 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> { self.imp.type_of_pat(pat) } + pub fn type_of_self(&self, param: &ast::SelfParam) -> Option { + self.imp.type_of_self(param) + } + pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option { self.imp.resolve_method_call(call) } @@ -216,6 +220,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.resolve_path(path) } + // TODO: id pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option { self.imp.resolve_variant(record_lit) } @@ -377,6 +382,10 @@ impl<'db> SemanticsImpl<'db> { self.analyze(pat.syntax()).type_of_pat(self.db, &pat) } + pub fn type_of_self(&self, param: &ast::SelfParam) -> Option { + self.analyze(param.syntax()).type_of_self(self.db, ¶m) + } + pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option { self.analyze(call.syntax()).resolve_method_call(self.db, call) } 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 { Some(res) } + // TODO: rename pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option { let expr_id = self.expr_id(db, expr)?; let ty = self.infer.as_ref()?[expr_id].clone(); @@ -127,6 +128,17 @@ impl SourceAnalyzer { Type::new_with_resolver(db, &self.resolver, ty) } + pub(crate) fn type_of_self( + &self, + db: &dyn HirDatabase, + param: &ast::SelfParam, + ) -> Option { + let src = InFile { file_id: self.file_id, value: param }; + let pat_id = self.body_source_map.as_ref()?.node_self_param(src)?; + let ty = self.infer.as_ref()?[pat_id].clone(); + Type::new_with_resolver(db, &self.resolver, ty) + } + pub(crate) fn resolve_method_call( &self, 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 { self.pat_map.get(&src).cloned() } + pub fn node_self_param(&self, node: InFile<&ast::SelfParam>) -> Option { + let src = node.map(|it| Either::Right(AstPtr::new(it))); + self.pat_map.get(&src).cloned() + } + pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile> { self.field_map[&(expr, field)].clone() } 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::{ ast::{self}, match_ast, AstNode, SyntaxKind::*, - SyntaxToken, TokenAtOffset, + SyntaxToken, TokenAtOffset, T, }; use crate::{ @@ -32,9 +32,10 @@ pub(crate) fn goto_definition( let file = sema.parse(position.file_id).syntax().clone(); let original_token = pick_best(file.token_at_offset(position.offset))?; let token = sema.descend_into_macros(original_token.clone()); + let parent = token.parent(); let nav_targets = match_ast! { - match (token.parent()) { + match parent { ast::NameRef(name_ref) => { reference_definition(&sema, &name_ref).to_vec() }, @@ -57,7 +58,7 @@ fn pick_best(tokens: TokenAtOffset) -> Option { return tokens.max_by_key(priority); fn priority(n: &SyntaxToken) -> usize { match n.kind() { - IDENT | INT_NUMBER => 2, + IDENT | INT_NUMBER | T![self] => 2, kind if kind.is_trivia() => 0, _ => 1, } @@ -121,7 +122,8 @@ mod tests { data => panic!("bad data: {}", data), } - let mut navs = analysis.goto_definition(position).unwrap().unwrap().info; + let mut navs = + analysis.goto_definition(position).unwrap().expect("no definition found").info; if navs.len() == 0 { panic!("unresolved reference") } 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 @@ use ra_ide_db::RootDatabase; -use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; +use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; @@ -25,8 +25,9 @@ pub(crate) fn goto_type_definition( let (ty, node) = sema.ancestors_with_macros(token.parent()).find_map(|node| { let ty = match_ast! { match node { - ast::Expr(expr) => sema.type_of_expr(&expr)?, - ast::Pat(pat) => sema.type_of_pat(&pat)?, + ast::Expr(it) => sema.type_of_expr(&it)?, + ast::Pat(it) => sema.type_of_pat(&it)?, + ast::SelfParam(it) => sema.type_of_self(&it)?, _ => return None, } }; @@ -44,7 +45,7 @@ fn pick_best(tokens: TokenAtOffset) -> Option { return tokens.max_by_key(priority); fn priority(n: &SyntaxToken) -> usize { match n.kind() { - IDENT | INT_NUMBER => 2, + IDENT | INT_NUMBER | T![self] => 2, kind if kind.is_trivia() => 0, _ => 1, } @@ -140,4 +141,18 @@ mod tests { "Foo STRUCT_DEF FileId(1) 0..11 7..10", ); } + + #[test] + fn goto_def_for_self_param() { + check_goto( + r#" +struct Foo; +impl Foo { + //^^^ + fn f(&self<|>) {} +} +"#, + "Foo STRUCT_DEF FileId(1) 0..11 7..10", + ) + } } -- cgit v1.2.3 From 9c54537ecf4694d02f45c7ca0a3828c08c0a0efd Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Jul 2020 14:09:31 +0200 Subject: Rename --- crates/ra_hir/src/semantics.rs | 2 +- crates/ra_hir/src/source_analyzer.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 6b6c5e494..4677eb561 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs @@ -375,7 +375,7 @@ impl<'db> SemanticsImpl<'db> { } pub fn type_of_expr(&self, expr: &ast::Expr) -> Option { - self.analyze(expr.syntax()).type_of(self.db, &expr) + self.analyze(expr.syntax()).type_of_expr(self.db, &expr) } pub fn type_of_pat(&self, pat: &ast::Pat) -> Option { diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 1f1bdc0d8..f74b78b23 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs @@ -115,8 +115,7 @@ impl SourceAnalyzer { Some(res) } - // TODO: rename - pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option { + pub(crate) fn type_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option { let expr_id = self.expr_id(db, expr)?; let ty = self.infer.as_ref()?[expr_id].clone(); Type::new_with_resolver(db, &self.resolver, ty) -- cgit v1.2.3 From f4147f6a341bda8f4a181a096b7dd726fc2d6b31 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Jul 2020 14:11:31 +0200 Subject: Dont expose ID --- crates/ra_hir/src/semantics.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 4677eb561..0d877e44e 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs @@ -25,7 +25,7 @@ use crate::{ semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, - Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, + Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, }; use resolver::TypeNs; @@ -220,9 +220,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.resolve_path(path) } - // TODO: id - pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option { - self.imp.resolve_variant(record_lit) + pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option { + self.imp.resolve_variant(record_lit).map(VariantDef::from) } pub fn lower_path(&self, path: &ast::Path) -> Option { -- cgit v1.2.3 From cd4502fd47ecd74ac52815fe8598b002ca1316a0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Jul 2020 14:39:05 +0200 Subject: Simplify tests --- crates/ra_ide/src/goto_type_definition.rs | 113 ++++++++++++++---------------- 1 file changed, 53 insertions(+), 60 deletions(-) diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index d9cf975d4..723c3e8ae 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs @@ -54,105 +54,98 @@ fn pick_best(tokens: TokenAtOffset) -> Option { #[cfg(test)] mod tests { - use crate::mock_analysis::analysis_and_position; + use ra_db::FileRange; - fn check_goto(ra_fixture: &str, expected: &str) { - let (analysis, pos) = analysis_and_position(ra_fixture); + use crate::mock_analysis::MockAnalysis; - let mut navs = analysis.goto_type_definition(pos).unwrap().unwrap().info; + fn check(ra_fixture: &str) { + let (mock, position) = MockAnalysis::with_files_and_position(ra_fixture); + let (expected, data) = mock.annotation(); + assert!(data.is_empty()); + let analysis = mock.analysis(); + + let mut navs = analysis.goto_type_definition(position).unwrap().unwrap().info; assert_eq!(navs.len(), 1); let nav = navs.pop().unwrap(); - nav.assert_match(expected); + assert_eq!(expected, FileRange { file_id: nav.file_id(), range: nav.range() }); } #[test] fn goto_type_definition_works_simple() { - check_goto( - r" - //- /lib.rs - struct Foo; - fn foo() { - let f: Foo; - f<|> - } - ", - "Foo STRUCT_DEF FileId(1) 0..11 7..10", + check( + r#" +struct Foo; + //^^^ +fn foo() { + let f: Foo; f<|> +} +"#, ); } #[test] fn goto_type_definition_works_simple_ref() { - check_goto( - r" - //- /lib.rs - struct Foo; - fn foo() { - let f: &Foo; - f<|> - } - ", - "Foo STRUCT_DEF FileId(1) 0..11 7..10", + check( + r#" +struct Foo; + //^^^ +fn foo() { + let f: &Foo; f<|> +} +"#, ); } #[test] fn goto_type_definition_works_through_macro() { - check_goto( - r" - //- /lib.rs - macro_rules! id { - ($($tt:tt)*) => { $($tt)* } - } - struct Foo {} - id! { - fn bar() { - let f<|> = Foo {}; - } - } - ", - "Foo STRUCT_DEF FileId(1) 52..65 59..62", + check( + r#" +macro_rules! id { ($($tt:tt)*) => { $($tt)* } } +struct Foo {} + //^^^ +id! { + fn bar() { let f<|> = Foo {}; } +} +"#, ); } #[test] fn goto_type_definition_for_param() { - check_goto( - r" - //- /lib.rs - struct Foo; - fn foo(<|>f: Foo) {} - ", - "Foo STRUCT_DEF FileId(1) 0..11 7..10", + check( + r#" +struct Foo; + //^^^ +fn foo(<|>f: Foo) {} +"#, ); } #[test] fn goto_type_definition_for_tuple_field() { - check_goto( - r" - //- /lib.rs - struct Foo; - struct Bar(Foo); - fn foo() { - let bar = Bar(Foo); - bar.<|>0; - } - ", - "Foo STRUCT_DEF FileId(1) 0..11 7..10", + check( + r#" +struct Foo; + //^^^ +struct Bar(Foo); +fn foo() { + let bar = Bar(Foo); + bar.<|>0; +} +"#, ); } #[test] fn goto_def_for_self_param() { - check_goto( + check( r#" struct Foo; + //^^^ impl Foo { - //^^^ fn f(&self<|>) {} } "#, - "Foo STRUCT_DEF FileId(1) 0..11 7..10", ) } } -- cgit v1.2.3 From 075380dd56439cdaf1967b7298e10b96b995fc07 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Jul 2020 14:42:26 +0200 Subject: Look through Arc for goto type definition --- crates/ra_ide/src/goto_type_definition.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index 723c3e8ae..069cb283e 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs @@ -35,7 +35,7 @@ pub(crate) fn goto_type_definition( Some((ty, node)) })?; - let adt_def = ty.autoderef(db).find_map(|ty| ty.as_adt())?; + let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?; let nav = adt_def.to_nav(db); Some(RangeInfo::new(node.text_range(), vec![nav])) -- cgit v1.2.3