From 16f67ee384d5b49358de167069535af727b87dba Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 28 Nov 2018 01:11:29 +0300 Subject: move resolve_local to Scopes --- crates/ra_analysis/src/hir/function/mod.rs | 28 ++++++++- crates/ra_analysis/src/hir/function/scope.rs | 29 ++++++++- crates/ra_analysis/src/hir/mod.rs | 53 ---------------- crates/ra_analysis/src/imp.rs | 93 ++++++++++++++-------------- crates/ra_analysis/src/syntax_ptr.rs | 7 +-- crates/ra_analysis/tests/tests.rs | 4 +- 6 files changed, 105 insertions(+), 109 deletions(-) (limited to 'crates') diff --git a/crates/ra_analysis/src/hir/function/mod.rs b/crates/ra_analysis/src/hir/function/mod.rs index 5e44a88a7..d171b6a8d 100644 --- a/crates/ra_analysis/src/hir/function/mod.rs +++ b/crates/ra_analysis/src/hir/function/mod.rs @@ -6,8 +6,8 @@ use std::{ }; use ra_syntax::{ + TextRange, TextUnit, SyntaxNodeRef, ast::{self, AstNode, DocCommentsOwner, NameOwner}, - TextRange, TextUnit, }; use crate::{ @@ -39,6 +39,32 @@ impl FunctionDescriptor { FunctionDescriptor { fn_id } } + pub(crate) fn guess_for_name_ref( + db: &impl HirDatabase, + file_id: FileId, + name_ref: ast::NameRef, + ) -> Option { + FunctionDescriptor::guess_for_node(db, file_id, name_ref.syntax()) + } + + pub(crate) fn guess_for_bind_pat( + db: &impl HirDatabase, + file_id: FileId, + bind_pat: ast::BindPat, + ) -> Option { + FunctionDescriptor::guess_for_node(db, file_id, bind_pat.syntax()) + } + + fn guess_for_node( + db: &impl HirDatabase, + file_id: FileId, + node: SyntaxNodeRef, + ) -> Option { + let fn_def = node.ancestors().find_map(ast::FnDef::cast)?; + let res = FunctionDescriptor::guess_from_source(db, file_id, fn_def); + Some(res) + } + pub(crate) fn scope(&self, db: &impl HirDatabase) -> Arc { db.fn_scopes(self.fn_id) } diff --git a/crates/ra_analysis/src/hir/function/scope.rs b/crates/ra_analysis/src/hir/function/scope.rs index b8bdebe47..76b2fea68 100644 --- a/crates/ra_analysis/src/hir/function/scope.rs +++ b/crates/ra_analysis/src/hir/function/scope.rs @@ -1,9 +1,9 @@ use rustc_hash::{FxHashMap, FxHashSet}; use ra_syntax::{ + AstNode, SmolStr, SyntaxNodeRef, TextRange, algo::generate, ast::{self, ArgListOwner, LoopBodyOwner, NameOwner}, - AstNode, SmolStr, SyntaxNodeRef, }; use crate::{ @@ -70,6 +70,27 @@ impl FnScopes { .nth(0); ret } + + pub fn find_all_refs(&self, pat: ast::BindPat) -> Vec { + let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); + let name_ptr = LocalSyntaxPtr::new(pat.syntax()); + let refs: Vec<_> = fn_def + .syntax() + .descendants() + .filter_map(ast::NameRef::cast) + .filter(|name_ref| match self.resolve_local_name(*name_ref) { + None => false, + Some(entry) => entry.ptr() == name_ptr, + }) + .map(|name_ref| ReferenceDescriptor { + name: name_ref.syntax().text().to_string(), + range: name_ref.syntax().range(), + }) + .collect(); + + refs + } + fn root_scope(&mut self) -> ScopeId { self.scopes.alloc(ScopeData { parent: None, @@ -262,6 +283,12 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { } } +#[derive(Debug)] +pub struct ReferenceDescriptor { + pub range: TextRange, + pub name: String, +} + #[cfg(test)] mod tests { use ra_editor::find_node_at_offset; diff --git a/crates/ra_analysis/src/hir/mod.rs b/crates/ra_analysis/src/hir/mod.rs index 5a9086cef..e234173a9 100644 --- a/crates/ra_analysis/src/hir/mod.rs +++ b/crates/ra_analysis/src/hir/mod.rs @@ -11,15 +11,9 @@ mod function; mod module; mod path; -use ra_syntax::{ - ast::{self, AstNode}, - TextRange, -}; - use crate::{ hir::db::HirDatabase, loc2id::{DefId, DefLoc}, - syntax_ptr::LocalSyntaxPtr, Cancelable, }; @@ -49,50 +43,3 @@ impl DefId { Ok(res) } } - -#[derive(Debug)] -pub struct ReferenceDescriptor { - pub range: TextRange, - pub name: String, -} - -#[derive(Debug)] -pub struct DeclarationDescriptor<'a> { - pat: ast::BindPat<'a>, - pub range: TextRange, -} - -impl<'a> DeclarationDescriptor<'a> { - pub fn new(pat: ast::BindPat) -> DeclarationDescriptor { - let range = pat.syntax().range(); - - DeclarationDescriptor { pat, range } - } - - pub fn find_all_refs(&self) -> Vec { - let name_ptr = LocalSyntaxPtr::new(self.pat.syntax()); - - let fn_def = match self.pat.syntax().ancestors().find_map(ast::FnDef::cast) { - Some(def) => def, - None => return Default::default(), - }; - - let fn_scopes = FnScopes::new(fn_def); - - let refs: Vec<_> = fn_def - .syntax() - .descendants() - .filter_map(ast::NameRef::cast) - .filter(|name_ref| match fn_scopes.resolve_local_name(*name_ref) { - None => false, - Some(entry) => entry.ptr() == name_ptr, - }) - .map(|name_ref| ReferenceDescriptor { - name: name_ref.syntax().text().to_string(), - range: name_ref.syntax().range(), - }) - .collect(); - - refs - } -} diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index b16edb969..377f7420f 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -7,7 +7,7 @@ use std::{ use ra_editor::{self, find_node_at_offset, FileSymbol, LineIndex, LocalEdit}; use ra_syntax::{ ast::{self, ArgListOwner, Expr, NameOwner}, - AstNode, SourceFileNode, SmolStr, + AstNode, SourceFileNode, SyntaxKind::*, SyntaxNodeRef, TextRange, TextUnit, }; @@ -22,7 +22,6 @@ use crate::{ hir::{ FunctionDescriptor, FnSignatureInfo, ModuleDescriptor, Problem, - DeclarationDescriptor, }, input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE}, symbol_index::SymbolIndex, @@ -273,24 +272,27 @@ impl AnalysisImpl { let file = self.db.file_syntax(position.file_id); let syntax = file.syntax(); if let Some(name_ref) = find_node_at_offset::(syntax, position.offset) { - // First try to resolve the symbol locally - return if let Some((name, range)) = - resolve_local_name(&self.db, position.file_id, name_ref) + if let Some(fn_descr) = + FunctionDescriptor::guess_for_name_ref(&*self.db, position.file_id, name_ref) { - let mut vec = vec![]; - vec.push(( - position.file_id, - FileSymbol { - name, - node_range: range, - kind: NAME, - }, - )); - Ok(vec) - } else { - // If that fails try the index based approach. - self.index_resolve(name_ref) - }; + let scope = fn_descr.scope(&*self.db); + // First try to resolve the symbol locally + return if let Some(entry) = scope.resolve_local_name(name_ref) { + let mut vec = vec![]; + vec.push(( + position.file_id, + FileSymbol { + name: entry.name().clone(), + node_range: entry.ptr().range(), + kind: NAME, + }, + )); + Ok(vec) + } else { + // If that fails try the index based approach. + self.index_resolve(name_ref) + }; + } } if let Some(name) = find_node_at_offset::(syntax, position.offset) { if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { @@ -320,31 +322,41 @@ impl AnalysisImpl { pub fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> { let file = self.db.file_syntax(position.file_id); - let syntax = file.syntax(); - // Find the binding associated with the offset - let maybe_binding = - find_node_at_offset::(syntax, position.offset).or_else(|| { - let name_ref = find_node_at_offset::(syntax, position.offset)?; - let resolved = resolve_local_name(&self.db, position.file_id, name_ref)?; - find_node_at_offset::(syntax, resolved.1.end()) - }); - - let binding = match maybe_binding { + let (binding, descr) = match find_binding(&self.db, &file, position) { None => return Vec::new(), Some(it) => it, }; - let decl = DeclarationDescriptor::new(binding); - - let mut ret = vec![(position.file_id, decl.range)]; + let mut ret = vec![(position.file_id, binding.syntax().range())]; ret.extend( - decl.find_all_refs() + descr + .scope(&*self.db) + .find_all_refs(binding) .into_iter() .map(|ref_desc| (position.file_id, ref_desc.range)), ); - ret + return ret; + + fn find_binding<'a>( + db: &db::RootDatabase, + source_file: &'a SourceFileNode, + position: FilePosition, + ) -> Option<(ast::BindPat<'a>, FunctionDescriptor)> { + let syntax = source_file.syntax(); + if let Some(binding) = find_node_at_offset::(syntax, position.offset) { + let descr = FunctionDescriptor::guess_for_bind_pat(db, position.file_id, binding)?; + return Some((binding, descr)); + }; + let name_ref = find_node_at_offset::(syntax, position.offset)?; + let descr = FunctionDescriptor::guess_for_name_ref(db, position.file_id, name_ref)?; + let scope = descr.scope(db); + let resolved = scope.resolve_local_name(name_ref)?; + let resolved = resolved.ptr().resolve(source_file); + let binding = find_node_at_offset::(syntax, resolved.range().end())?; + Some((binding, descr)) + } } pub fn doc_comment_for( @@ -582,16 +594,3 @@ impl<'a> FnCallNode<'a> { } } } - -fn resolve_local_name( - db: &db::RootDatabase, - file_id: FileId, - name_ref: ast::NameRef, -) -> Option<(SmolStr, TextRange)> { - let fn_def = name_ref.syntax().ancestors().find_map(ast::FnDef::cast)?; - let function = FunctionDescriptor::guess_from_source(db, file_id, fn_def); - let scopes = function.scope(db); - let scope_entry = scopes.resolve_local_name(name_ref)?; - let syntax = db.resolve_syntax_ptr(scope_entry.ptr().into_global(file_id)); - Some((scope_entry.name().clone(), syntax.range())) -} diff --git a/crates/ra_analysis/src/syntax_ptr.rs b/crates/ra_analysis/src/syntax_ptr.rs index e45934ce0..3168e82a7 100644 --- a/crates/ra_analysis/src/syntax_ptr.rs +++ b/crates/ra_analysis/src/syntax_ptr.rs @@ -56,11 +56,8 @@ impl LocalSyntaxPtr { } } - pub(crate) fn into_global(self, file_id: FileId) -> SyntaxPtr { - SyntaxPtr { - file_id, - local: self, - } + pub(crate) fn range(self) -> TextRange { + self.range } } diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index 72b2ebf97..8e7856027 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs @@ -10,10 +10,10 @@ use test_utils::assert_eq_dbg; use ra_analysis::{ mock_analysis::{analysis_and_position, single_file, single_file_with_position, MockAnalysis}, - AnalysisChange, CrateGraph, FileId, FnDescriptor, + AnalysisChange, CrateGraph, FileId, FnSignatureInfo, }; -fn get_signature(text: &str) -> (FnDescriptor, Option) { +fn get_signature(text: &str) -> (FnSignatureInfo, Option) { let (analysis, position) = single_file_with_position(text); analysis.resolve_callable(position).unwrap().unwrap() } -- cgit v1.2.3