From 406f366ccc8b903f457cc694dc1214794c0cfc88 Mon Sep 17 00:00:00 2001 From: "Jeremy A. Kolb" Date: Wed, 24 Oct 2018 14:24:32 -0400 Subject: [PATCH] Add DeclarationDescriptor and ReferenceDescriptor Fixes #142 Fixes #146 --- crates/ra_analysis/src/descriptors/mod.rs | 57 +++++++++++++++++++++-- crates/ra_analysis/src/imp.rs | 13 +++++- crates/ra_analysis/tests/tests.rs | 11 +++++ 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs index 0c4991757d..e27f8314ad 100644 --- a/crates/ra_analysis/src/descriptors/mod.rs +++ b/crates/ra_analysis/src/descriptors/mod.rs @@ -5,16 +5,17 @@ use std::sync::Arc; use ra_syntax::{ SmolStr, - ast::{FnDefNode}, + ast::{self, AstNode, FnDefNode}, + TextRange }; use crate::{ FileId, Cancelable, db::SyntaxDatabase, descriptors::module::{ModuleTree, ModuleId, ModuleScope}, - descriptors::function::{FnId, FnScopes}, + descriptors::function::{FnId, FnScopes, resolve_local_name}, input::SourceRootId, - syntax_ptr::SyntaxPtrDatabase, + syntax_ptr::{SyntaxPtrDatabase, LocalSyntaxPtr}, }; @@ -44,3 +45,53 @@ salsa::query_group! { } } } + +#[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 resolve_local_name(*name_ref, &fn_scopes) { + 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 b3c094041c..f950a79957 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -22,7 +22,7 @@ use crate::{ }, input::{SourceRootId, FilesDatabase, SourceRoot, WORKSPACE}, descriptors::{ - DescriptorDatabase, + DescriptorDatabase, DeclarationDescriptor, module::{ModuleTree, Problem}, function::{FnDescriptor, FnId}, }, @@ -327,6 +327,17 @@ impl AnalysisImpl { let mut ret = vec![]; + if let Some(binding) = find_node_at_offset::(syntax, offset) { + let decl = DeclarationDescriptor::new(binding); + + ret.push((file_id, decl.range)); + + ret.extend(decl.find_all_refs().into_iter() + .map(|ref_desc| (file_id, ref_desc.range ))); + + return ret; + } + // Find the symbol we are looking for if let Some(name_ref) = find_node_at_offset::(syntax, offset) { diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index 9e2478d9e8..22d27cdbe8 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs @@ -377,6 +377,17 @@ fn test_find_all_refs_for_param_inside() { assert_eq!(refs.len(), 2); } +#[test] +fn test_find_all_refs_for_fn_param() { + let code = r#" + fn foo(i<|> : u32) -> u32 { + i + }"#; + + let refs = get_all_refs(code); + assert_eq!(refs.len(), 2); +} + #[test] fn test_complete_crate_path() { let (analysis, position) = analysis_and_position("