From fbc3ffcee6eec3d89e27417b3d3543327d810299 Mon Sep 17 00:00:00 2001 From: Mikhail Modin Date: Sat, 18 Jan 2020 12:17:34 +0000 Subject: Improves reference search by StructLiteral --- crates/ra_ide/src/references.rs | 138 ++++++++++++++++++++++++++++++++-------- 1 file changed, 111 insertions(+), 27 deletions(-) (limited to 'crates/ra_ide/src/references.rs') diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index 5e2fe1905..ebded715d 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs @@ -112,25 +112,20 @@ impl IntoIterator for ReferenceSearchResult { pub(crate) fn find_all_refs( db: &RootDatabase, - mut position: FilePosition, + position: FilePosition, search_scope: Option, ) -> Option> { let parse = db.parse(position.file_id); let syntax = parse.tree().syntax().clone(); - let token = syntax.token_at_offset(position.offset); - let mut search_kind = ReferenceKind::Other; + let (opt_name, search_kind) = + if let Some(name) = get_struct_def_name_for_struc_litetal_search(&syntax, position) { + (Some(name), ReferenceKind::StructLiteral) + } else { + (find_node_at_offset::(&syntax, position.offset), ReferenceKind::Other) + }; - if let TokenAtOffset::Between(ref left, ref right) = token { - if (right.kind() == SyntaxKind::L_CURLY || right.kind() == SyntaxKind::L_PAREN) - && left.kind() != SyntaxKind::IDENT - { - position = FilePosition { offset: left.text_range().start(), ..position }; - search_kind = ReferenceKind::StructLiteral; - } - } - - let RangeInfo { range, info: (name, def) } = find_name(db, &syntax, position)?; + let RangeInfo { range, info: (name, def) } = find_name(db, &syntax, position, opt_name)?; let declaration = match def.kind { NameKind::Macro(mac) => mac.to_nav(db), @@ -170,9 +165,10 @@ fn find_name( db: &RootDatabase, syntax: &SyntaxNode, position: FilePosition, + opt_name: Option, ) -> Option> { let mut sb = SourceBinder::new(db); - if let Some(name) = find_node_at_offset::(&syntax, position.offset) { + if let Some(name) = opt_name { let def = classify_name(&mut sb, InFile::new(position.file_id.into(), &name))?; let range = name.syntax().text_range(); return Some(RangeInfo::new(range, (name.text().to_string(), def))); @@ -218,15 +214,8 @@ fn process_definition( if let Some(d) = classify_name_ref(&mut sb, InFile::new(file_id.into(), &name_ref)) { if d == def { - let kind = if name_ref - .syntax() - .ancestors() - .find_map(ast::RecordLit::cast) - .and_then(|l| l.path()) - .and_then(|p| p.segment()) - .and_then(|p| p.name_ref()) - .map(|n| n == name_ref) - .unwrap_or(false) + let kind = if is_record_lit_name_ref(&name_ref) + || is_call_expr_name_ref(&name_ref) { ReferenceKind::StructLiteral } else { @@ -301,6 +290,49 @@ fn reference_access(kind: &NameKind, name_ref: &ast::NameRef) -> Option bool { + name_ref + .syntax() + .ancestors() + .find_map(ast::RecordLit::cast) + .and_then(|l| l.path()) + .and_then(|p| p.segment()) + .map(|p| p.name_ref().as_ref() == Some(name_ref)) + .unwrap_or(false) +} + +fn get_struct_def_name_for_struc_litetal_search( + syntax: &SyntaxNode, + position: FilePosition, +) -> Option { + if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) { + if right.kind() != SyntaxKind::L_CURLY && right.kind() != SyntaxKind::L_PAREN { + return None; + } + if let Some(name) = find_node_at_offset::(&syntax, left.text_range().start()) { + return name.syntax().ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name()); + } + if find_node_at_offset::(&syntax, left.text_range().start()).is_some() { + return left.ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name()); + } + } + None +} + +fn is_call_expr_name_ref(name_ref: &ast::NameRef) -> bool { + name_ref + .syntax() + .ancestors() + .find_map(ast::CallExpr::cast) + .and_then(|c| match c.expr()? { + ast::Expr::PathExpr(p) => { + Some(p.path()?.segment()?.name_ref().as_ref() == Some(name_ref)) + } + _ => None, + }) + .unwrap_or(false) +} + #[cfg(test)] mod tests { use crate::{ @@ -309,7 +341,7 @@ mod tests { }; #[test] - fn test_struct_literal() { + fn test_struct_literal_after_space() { let code = r#" struct Foo <|>{ a: i32, @@ -330,6 +362,58 @@ mod tests { ); } + #[test] + fn test_struct_literal_befor_space() { + let code = r#" + struct Foo<|> {} + fn main() { + let f: Foo; + f = Foo {}; + }"#; + + let refs = get_all_refs(code); + check_result( + refs, + "Foo STRUCT_DEF FileId(1) [5; 18) [12; 15) Other", + &["FileId(1) [54; 57) Other", "FileId(1) [71; 74) StructLiteral"], + ); + } + + #[test] + fn test_struct_literal_with_generic_type() { + let code = r#" + struct Foo <|>{} + fn main() { + let f: Foo::; + f = Foo {}; + }"#; + + let refs = get_all_refs(code); + check_result( + refs, + "Foo STRUCT_DEF FileId(1) [5; 21) [12; 15) Other", + &["FileId(1) [81; 84) StructLiteral"], + ); + } + + #[test] + fn test_struct_literal_for_tuple() { + let code = r#" + struct Foo<|>(i32); + + fn main() { + let f: Foo; + f = Foo(1); + }"#; + + let refs = get_all_refs(code); + check_result( + refs, + "Foo STRUCT_DEF FileId(1) [5; 21) [12; 15) Other", + &["FileId(1) [71; 74) StructLiteral"], + ); + } + #[test] fn test_find_all_refs_for_local() { let code = r#" @@ -564,7 +648,7 @@ mod tests { check_result( refs, "quux FN_DEF FileId(1) [18; 34) [25; 29) Other", - &["FileId(2) [16; 20) Other", "FileId(3) [16; 20) Other"], + &["FileId(2) [16; 20) StructLiteral", "FileId(3) [16; 20) StructLiteral"], ); let refs = @@ -572,7 +656,7 @@ mod tests { check_result( refs, "quux FN_DEF FileId(1) [18; 34) [25; 29) Other", - &["FileId(3) [16; 20) Other"], + &["FileId(3) [16; 20) StructLiteral"], ); } @@ -591,7 +675,7 @@ mod tests { check_result( refs, "m1 MACRO_CALL FileId(1) [9; 63) [46; 48) Other", - &["FileId(1) [96; 98) Other", "FileId(1) [114; 116) Other"], + &["FileId(1) [96; 98) StructLiteral", "FileId(1) [114; 116) StructLiteral"], ); } -- cgit v1.2.3 From 88267c86c0c49de395973574d2516ab904091cfb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 6 Feb 2020 12:52:32 +0100 Subject: cleanup imports --- crates/ra_ide/src/references.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'crates/ra_ide/src/references.rs') diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index ebded715d..b47f8bcd9 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs @@ -17,6 +17,7 @@ mod search_scope; use hir::{InFile, SourceBinder}; use once_cell::unsync::Lazy; use ra_db::{SourceDatabase, SourceDatabaseExt}; +use ra_ide_db::RootDatabase; use ra_prof::profile; use ra_syntax::{ algo::find_node_at_offset, @@ -24,9 +25,7 @@ use ra_syntax::{ match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, TextUnit, TokenAtOffset, }; -use crate::{ - db::RootDatabase, display::ToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, -}; +use crate::{display::ToNav, FilePosition, FileRange, NavigationTarget, RangeInfo}; pub(crate) use self::{ classify::{classify_name, classify_name_ref}, -- cgit v1.2.3 From 271017e6bf5b5f46464d09db7fc869c92998fc80 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 6 Feb 2020 16:23:28 +0100 Subject: Move NameKind up --- crates/ra_ide/src/references.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'crates/ra_ide/src/references.rs') diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index b47f8bcd9..c215040f4 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs @@ -10,7 +10,6 @@ //! resolved to the search element definition, we get a reference. mod classify; -mod name_definition; mod rename; mod search_scope; @@ -29,9 +28,9 @@ use crate::{display::ToNav, FilePosition, FileRange, NavigationTarget, RangeInfo pub(crate) use self::{ classify::{classify_name, classify_name_ref}, - name_definition::{NameDefinition, NameKind}, rename::rename, }; +pub(crate) use ra_ide_db::defs::{NameDefinition, NameKind}; pub use self::search_scope::SearchScope; @@ -137,7 +136,7 @@ pub(crate) fn find_all_refs( }; let search_scope = { - let base = def.search_scope(db); + let base = SearchScope::for_def(&def, db); match search_scope { None => base, Some(scope) => base.intersection(&scope), -- cgit v1.2.3 From f55be75a17dab2ca23b34c45e7597fe19a5fc8e4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 7 Feb 2020 12:51:12 +0100 Subject: Remove irrelevant distinction --- crates/ra_ide/src/references.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'crates/ra_ide/src/references.rs') diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index c215040f4..612ed84b7 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs @@ -128,7 +128,6 @@ pub(crate) fn find_all_refs( let declaration = match def.kind { NameKind::Macro(mac) => mac.to_nav(db), NameKind::Field(field) => field.to_nav(db), - NameKind::AssocItem(assoc) => assoc.to_nav(db), NameKind::Def(def) => NavigationTarget::from_def(db, def)?, NameKind::SelfType(imp) => imp.to_nav(db), NameKind::Local(local) => local.to_nav(db), -- cgit v1.2.3 From ae70d072374f3c4d14abdccbe61661cf02b41b33 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 7 Feb 2020 14:26:59 +0100 Subject: Rename --- crates/ra_ide/src/references.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'crates/ra_ide/src/references.rs') diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index 612ed84b7..a6320bd2f 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs @@ -127,8 +127,8 @@ pub(crate) fn find_all_refs( let declaration = match def.kind { NameKind::Macro(mac) => mac.to_nav(db), - NameKind::Field(field) => field.to_nav(db), - NameKind::Def(def) => NavigationTarget::from_def(db, def)?, + NameKind::StructField(field) => field.to_nav(db), + NameKind::ModuleDef(def) => NavigationTarget::from_def(db, def)?, NameKind::SelfType(imp) => imp.to_nav(db), NameKind::Local(local) => local.to_nav(db), NameKind::TypeParam(_) => return None, @@ -239,7 +239,7 @@ fn decl_access( range: TextRange, ) -> Option { match kind { - NameKind::Local(_) | NameKind::Field(_) => {} + NameKind::Local(_) | NameKind::StructField(_) => {} _ => return None, }; @@ -259,7 +259,7 @@ fn decl_access( fn reference_access(kind: &NameKind, name_ref: &ast::NameRef) -> Option { // Only Locals and Fields have accesses for now. match kind { - NameKind::Local(_) | NameKind::Field(_) => {} + NameKind::Local(_) | NameKind::StructField(_) => {} _ => return None, }; -- cgit v1.2.3