Add DeclarationDescriptor and ReferenceDescriptor

Fixes #142
Fixes #146
This commit is contained in:
Jeremy A. Kolb 2018-10-24 14:24:32 -04:00 committed by Aleksey Kladov
parent 55ebe6380a
commit 406f366ccc
3 changed files with 77 additions and 4 deletions

View file

@ -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<ReferenceDescriptor> {
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
}
}

View file

@ -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::<ast::BindPat>(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::<ast::NameRef>(syntax, offset) {

View file

@ -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("