From 10d66d63d716a10ba7a5a8d1b69c9066249caf69 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 10 Apr 2019 11:15:55 +0300 Subject: introduce SourceAnalyzer --- crates/ra_hir/src/expr/scope.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_hir/src/expr/scope.rs') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 725b6c00e..404c979eb 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -109,7 +109,7 @@ impl ExprScopes { #[derive(Debug, Clone, PartialEq, Eq)] pub struct ScopesWithSourceMap { - pub source_map: Arc, + pub(crate) source_map: Arc, pub scopes: Arc, } -- cgit v1.2.3 From 3aae223d938e5a36d997c45a0f86cfcabf83b570 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 09:31:03 +0300 Subject: hide some scopes --- crates/ra_hir/src/expr/scope.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir/src/expr/scope.rs') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 404c979eb..a9be9fbdb 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -173,7 +173,10 @@ impl ScopesWithSourceMap { .unwrap_or(original_scope) } - pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option { + pub(crate) fn resolve_local_name( + &self, + name_ref: &ast::NameRef, + ) -> Option { let mut shadowed = FxHashSet::default(); let name = name_ref.as_name(); let ret = self @@ -190,7 +193,7 @@ impl ScopesWithSourceMap { }) } - pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec { + pub(crate) fn find_all_refs(&self, pat: &ast::BindPat) -> Vec { let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); let ptr = Either::A(AstPtr::new(pat.into())); fn_def -- cgit v1.2.3 From 30481808fbfea109f324dfaf93daaaebacc75333 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 09:53:02 +0300 Subject: make stuff private --- crates/ra_hir/src/expr/scope.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir/src/expr/scope.rs') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index a9be9fbdb..dcec51a10 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -110,7 +110,7 @@ impl ExprScopes { #[derive(Debug, Clone, PartialEq, Eq)] pub struct ScopesWithSourceMap { pub(crate) source_map: Arc, - pub scopes: Arc, + pub(crate) scopes: Arc, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -134,7 +134,7 @@ impl ScopesWithSourceMap { generate(self.scope_for(node), move |&scope| self.scopes.scopes[scope].parent) } - pub fn scope_for_offset(&self, offset: TextUnit) -> Option { + pub(crate) fn scope_for_offset(&self, offset: TextUnit) -> Option { self.scopes .scope_for .iter() @@ -211,7 +211,7 @@ impl ScopesWithSourceMap { .collect() } - pub fn scope_for(&self, node: &SyntaxNode) -> Option { + pub(crate) fn scope_for(&self, node: &SyntaxNode) -> Option { node.ancestors() .map(SyntaxNodePtr::new) .filter_map(|ptr| self.source_map.syntax_expr(ptr)) -- cgit v1.2.3 From f4a94e74bcd6c8f9275a57a775e64314af1878da Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 10:49:01 +0300 Subject: fold ScopeWithSyntax into SourceAnalyzer --- crates/ra_hir/src/expr/scope.rs | 166 +++++++--------------------------------- 1 file changed, 28 insertions(+), 138 deletions(-) (limited to 'crates/ra_hir/src/expr/scope.rs') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index dcec51a10..476385a2f 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -1,17 +1,16 @@ use std::sync::Arc; -use rustc_hash::{FxHashMap, FxHashSet}; - +use rustc_hash::{FxHashMap}; use ra_syntax::{ - AstNode, SyntaxNode, TextUnit, TextRange, SyntaxNodePtr, AstPtr, + TextRange, AstPtr, algo::generate, ast, }; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ - Name, AsName,DefWithBody, Either, - expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySourceMap}, + Name, DefWithBody, Either, + expr::{PatId, ExprId, Pat, Expr, Body, Statement}, HirDatabase, }; @@ -23,7 +22,7 @@ impl_arena_id!(ScopeId); pub struct ExprScopes { body: Arc, scopes: Arena, - scope_for: FxHashMap, + pub(crate) scope_for: FxHashMap, } #[derive(Debug, PartialEq, Eq)] @@ -66,10 +65,7 @@ impl ExprScopes { &self.scopes[scope].entries } - pub fn scope_chain_for<'a>( - &'a self, - scope: Option, - ) -> impl Iterator + 'a { + pub fn scope_chain<'a>(&'a self, scope: Option) -> impl Iterator + 'a { generate(scope, move |&scope| self.scopes[scope].parent) } @@ -107,16 +103,10 @@ impl ExprScopes { } } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ScopesWithSourceMap { - pub(crate) source_map: Arc, - pub(crate) scopes: Arc, -} - #[derive(Debug, Clone, PartialEq, Eq)] pub struct ScopeEntryWithSyntax { - name: Name, - ptr: Either, AstPtr>, + pub(crate) name: Name, + pub(crate) ptr: Either, AstPtr>, } impl ScopeEntryWithSyntax { @@ -129,96 +119,6 @@ impl ScopeEntryWithSyntax { } } -impl ScopesWithSourceMap { - fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator + 'a { - generate(self.scope_for(node), move |&scope| self.scopes.scopes[scope].parent) - } - - pub(crate) fn scope_for_offset(&self, offset: TextUnit) -> Option { - self.scopes - .scope_for - .iter() - .filter_map(|(id, scope)| Some((self.source_map.expr_syntax(*id)?, scope))) - // find containing scope - .min_by_key(|(ptr, _scope)| { - (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len()) - }) - .map(|(ptr, scope)| self.adjust(ptr, *scope, offset)) - } - - // XXX: during completion, cursor might be outside of any particular - // expression. Try to figure out the correct scope... - // FIXME: move this to source binder? - fn adjust(&self, ptr: SyntaxNodePtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId { - let r = ptr.range(); - let child_scopes = self - .scopes - .scope_for - .iter() - .filter_map(|(id, scope)| Some((self.source_map.expr_syntax(*id)?, scope))) - .map(|(ptr, scope)| (ptr.range(), scope)) - .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r); - - child_scopes - .max_by(|(r1, _), (r2, _)| { - if r2.is_subrange(&r1) { - std::cmp::Ordering::Greater - } else if r1.is_subrange(&r2) { - std::cmp::Ordering::Less - } else { - r1.start().cmp(&r2.start()) - } - }) - .map(|(_ptr, scope)| *scope) - .unwrap_or(original_scope) - } - - pub(crate) fn resolve_local_name( - &self, - name_ref: &ast::NameRef, - ) -> Option { - let mut shadowed = FxHashSet::default(); - let name = name_ref.as_name(); - let ret = self - .scope_chain(name_ref.syntax()) - .flat_map(|scope| self.scopes.entries(scope).iter()) - .filter(|entry| shadowed.insert(entry.name())) - .filter(|entry| entry.name() == &name) - .nth(0); - ret.and_then(|entry| { - Some(ScopeEntryWithSyntax { - name: entry.name().clone(), - ptr: self.source_map.pat_syntax(entry.pat())?, - }) - }) - } - - pub(crate) fn find_all_refs(&self, pat: &ast::BindPat) -> Vec { - let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); - let ptr = Either::A(AstPtr::new(pat.into())); - 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() == ptr, - }) - .map(|name_ref| ReferenceDescriptor { - name: name_ref.syntax().text().to_string(), - range: name_ref.syntax().range(), - }) - .collect() - } - - pub(crate) fn scope_for(&self, node: &SyntaxNode) -> Option { - node.ancestors() - .map(SyntaxNodePtr::new) - .filter_map(|ptr| self.source_map.syntax_expr(ptr)) - .find_map(|it| self.scopes.scope_for(it)) - } -} - impl ScopeEntry { pub fn name(&self) -> &Name { &self.name @@ -297,12 +197,11 @@ pub struct ReferenceDescriptor { #[cfg(test)] mod tests { - use ra_db::salsa::InternKey; - use ra_syntax::{SourceFile, algo::find_node_at_offset}; + use ra_db::SourceDatabase; + use ra_syntax::{algo::find_node_at_offset, AstNode, SyntaxNodePtr}; use test_utils::{extract_offset, assert_eq_text}; - use crate::Function; - use crate::expr::{ExprCollector}; + use crate::{source_binder::SourceAnalyzer, mock::MockDatabase}; use super::*; @@ -316,18 +215,20 @@ mod tests { buf.push_str(&code[off..]); buf }; - let file = SourceFile::parse(&code); + + let (db, _source_root, file_id) = MockDatabase::with_single_file(&code); + let file = db.parse(file_id); let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); - let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); - let irrelevant_function = - Function { id: crate::ids::FunctionId::from_intern_id(0u32.into()) }; - let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def); - let scopes = ExprScopes::new(Arc::new(body)); - let scopes = - ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) }; + let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); + + let scopes = analyzer.scopes(); + let expr_id = + analyzer.body_source_map().syntax_expr(SyntaxNodePtr::new(marker.syntax())).unwrap(); + let scope = scopes.scope_for(expr_id); + let actual = scopes - .scope_chain(marker.syntax()) - .flat_map(|scope| scopes.scopes.entries(scope)) + .scope_chain(scope) + .flat_map(|scope| scopes.entries(scope)) .map(|it| it.name().to_string()) .collect::>() .join("\n"); @@ -410,28 +311,17 @@ mod tests { ); } - fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> (Body, BodySourceMap) { - let mut collector = ExprCollector::new(DefWithBody::Function(function)); - collector.collect_fn_body(node); - collector.finish() - } - fn do_check_local_name(code: &str, expected_offset: u32) { let (off, code) = extract_offset(code); - let file = SourceFile::parse(&code); + + let (db, _source_root, file_id) = MockDatabase::with_single_file(&code); + let file = db.parse(file_id); let expected_name = find_node_at_offset::(file.syntax(), expected_offset.into()) .expect("failed to find a name at the target offset"); - - let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); + let analyzer = SourceAnalyzer::new(&db, file_id, name_ref.syntax(), None); - let irrelevant_function = - Function { id: crate::ids::FunctionId::from_intern_id(0u32.into()) }; - let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def); - let scopes = ExprScopes::new(Arc::new(body)); - let scopes = - ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) }; - let local_name_entry = scopes.resolve_local_name(name_ref).unwrap(); + let local_name_entry = analyzer.resolve_local_name(name_ref).unwrap(); let local_name = local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); assert_eq!(local_name.range(), expected_name.syntax().range()); -- cgit v1.2.3 From 4f8dc1b9f0fd544b0565dc95bb3f14478aa467bf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:06:53 +0300 Subject: make expr scope stuff private --- crates/ra_hir/src/expr/scope.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'crates/ra_hir/src/expr/scope.rs') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 476385a2f..4ac797eb7 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use rustc_hash::{FxHashMap}; use ra_syntax::{ TextRange, AstPtr, - algo::generate, ast, }; use ra_arena::{Arena, RawId, impl_arena_id}; @@ -26,13 +25,13 @@ pub struct ExprScopes { } #[derive(Debug, PartialEq, Eq)] -pub struct ScopeEntry { +pub(crate) struct ScopeEntry { name: Name, pat: PatId, } #[derive(Debug, PartialEq, Eq)] -pub struct ScopeData { +pub(crate) struct ScopeData { parent: Option, entries: Vec, } @@ -57,16 +56,15 @@ impl ExprScopes { scopes } - pub fn body(&self) -> Arc { - self.body.clone() - } - - pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { + pub(crate) fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { &self.scopes[scope].entries } - pub fn scope_chain<'a>(&'a self, scope: Option) -> impl Iterator + 'a { - generate(scope, move |&scope| self.scopes[scope].parent) + pub(crate) fn scope_chain<'a>( + &'a self, + scope: Option, + ) -> impl Iterator + 'a { + std::iter::successors(scope, move |&scope| self.scopes[scope].parent) } fn root_scope(&mut self) -> ScopeId { @@ -98,7 +96,7 @@ impl ExprScopes { self.scope_for.insert(node, scope); } - pub fn scope_for(&self, expr: ExprId) -> Option { + pub(crate) fn scope_for(&self, expr: ExprId) -> Option { self.scope_for.get(&expr).map(|&scope| scope) } } -- cgit v1.2.3 From d387bdccba2b5bb681e5b6c84cc1b0efe5c1a79a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:21:32 +0300 Subject: drop obsolete fixme --- crates/ra_hir/src/expr/scope.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'crates/ra_hir/src/expr/scope.rs') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 4ac797eb7..6a6de5772 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -37,7 +37,6 @@ pub(crate) struct ScopeData { } impl ExprScopes { - // FIXME: This should take something more general than Function pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { let body = db.body_hir(def); let res = ExprScopes::new(body); -- cgit v1.2.3 From f9e825d95624129b66c34f25904f6ae46b9d5760 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:24:09 +0300 Subject: move ScopeEntryWithSyntax --- crates/ra_hir/src/expr/scope.rs | 45 ++++++++++++----------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) (limited to 'crates/ra_hir/src/expr/scope.rs') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 6a6de5772..090343d12 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -1,14 +1,11 @@ use std::sync::Arc; -use rustc_hash::{FxHashMap}; -use ra_syntax::{ - TextRange, AstPtr, - ast, -}; +use rustc_hash::FxHashMap; +use ra_syntax::TextRange; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ - Name, DefWithBody, Either, + Name, DefWithBody, expr::{PatId, ExprId, Pat, Expr, Body, Statement}, HirDatabase, }; @@ -30,6 +27,16 @@ pub(crate) struct ScopeEntry { pat: PatId, } +impl ScopeEntry { + pub(crate) fn name(&self) -> &Name { + &self.name + } + + pub(crate) fn pat(&self) -> PatId { + self.pat + } +} + #[derive(Debug, PartialEq, Eq)] pub(crate) struct ScopeData { parent: Option, @@ -100,32 +107,6 @@ impl ExprScopes { } } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ScopeEntryWithSyntax { - pub(crate) name: Name, - pub(crate) ptr: Either, AstPtr>, -} - -impl ScopeEntryWithSyntax { - pub fn name(&self) -> &Name { - &self.name - } - - pub fn ptr(&self) -> Either, AstPtr> { - self.ptr - } -} - -impl ScopeEntry { - pub fn name(&self) -> &Name { - &self.name - } - - pub fn pat(&self) -> PatId { - self.pat - } -} - fn compute_block_scopes( statements: &[Statement], tail: Option, -- cgit v1.2.3 From b260641e0caa3938151afe66fa3bf5691b8c3caa Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:29:47 +0300 Subject: slight encapsulation --- crates/ra_hir/src/expr/scope.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'crates/ra_hir/src/expr/scope.rs') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 090343d12..7f53f23aa 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -18,7 +18,7 @@ impl_arena_id!(ScopeId); pub struct ExprScopes { body: Arc, scopes: Arena, - pub(crate) scope_for: FxHashMap, + scope_by_expr: FxHashMap, } #[derive(Debug, PartialEq, Eq)] @@ -54,7 +54,7 @@ impl ExprScopes { let mut scopes = ExprScopes { body: body.clone(), scopes: Arena::default(), - scope_for: FxHashMap::default(), + scope_by_expr: FxHashMap::default(), }; let root = scopes.root_scope(); scopes.add_params_bindings(root, body.params()); @@ -73,6 +73,14 @@ impl ExprScopes { std::iter::successors(scope, move |&scope| self.scopes[scope].parent) } + pub(crate) fn scope_for(&self, expr: ExprId) -> Option { + self.scope_by_expr.get(&expr).map(|&scope| scope) + } + + pub(crate) fn scope_by_expr(&self) -> &FxHashMap { + &self.scope_by_expr + } + fn root_scope(&mut self) -> ScopeId { self.scopes.alloc(ScopeData { parent: None, entries: vec![] }) } @@ -99,11 +107,7 @@ impl ExprScopes { } fn set_scope(&mut self, node: ExprId, scope: ScopeId) { - self.scope_for.insert(node, scope); - } - - pub(crate) fn scope_for(&self, expr: ExprId) -> Option { - self.scope_for.get(&expr).map(|&scope| scope) + self.scope_by_expr.insert(node, scope); } } -- cgit v1.2.3 From 2facb5e061971afbf6bd2fabe3966d5de9d46489 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:32:58 +0300 Subject: cleanups --- crates/ra_hir/src/expr/scope.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'crates/ra_hir/src/expr/scope.rs') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 7f53f23aa..58f365128 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -1,7 +1,6 @@ use std::sync::Arc; use rustc_hash::FxHashMap; -use ra_syntax::TextRange; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ @@ -171,22 +170,14 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope }; } -#[derive(Debug)] -pub struct ReferenceDescriptor { - pub range: TextRange, - pub name: String, -} - #[cfg(test)] mod tests { use ra_db::SourceDatabase; - use ra_syntax::{algo::find_node_at_offset, AstNode, SyntaxNodePtr}; + use ra_syntax::{algo::find_node_at_offset, AstNode, SyntaxNodePtr, ast}; use test_utils::{extract_offset, assert_eq_text}; use crate::{source_binder::SourceAnalyzer, mock::MockDatabase}; - use super::*; - fn do_check(code: &str, expected: &[&str]) { let (off, code) = extract_offset(code); let code = { -- cgit v1.2.3