move resolve local name

This commit is contained in:
Aleksey Kladov 2018-10-31 15:13:49 +03:00
parent b67295134b
commit c02be1502c
7 changed files with 31 additions and 94 deletions

View File

@ -10,7 +10,7 @@ use crate::{
syntax_ptr::SyntaxPtr
};
pub(crate) use self::scope::FnScopes;
pub(crate) use self::scope::{FnScopes, resolve_local_name};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

View File

@ -1,4 +1,4 @@
use rustc_hash::FxHashMap;
use rustc_hash::{FxHashMap, FxHashSet};
use ra_syntax::{
algo::generate,
@ -261,8 +261,6 @@ pub fn resolve_local_name<'a>(
name_ref: ast::NameRef,
scopes: &'a FnScopes,
) -> Option<&'a ScopeEntry> {
use rustc_hash::FxHashSet;
let mut shadowed = FxHashSet::default();
let ret = scopes
.scope_chain(name_ref.syntax())

View File

@ -3,7 +3,7 @@ use std::{
sync::Arc,
};
use ra_editor::{self, find_node_at_offset, resolve_local_name, FileSymbol, LineIndex, LocalEdit, CompletionItem};
use ra_editor::{self, find_node_at_offset, FileSymbol, LineIndex, LocalEdit, CompletionItem};
use ra_syntax::{
ast::{self, ArgListOwner, Expr, NameOwner},
AstNode, File, SmolStr,
@ -21,10 +21,13 @@ use crate::{
self, SyntaxDatabase, FileSyntaxQuery,
},
input::{SourceRootId, FilesDatabase, SourceRoot, WORKSPACE},
descriptors::DescriptorDatabase,
descriptors::module::{ModuleTree, Problem},
descriptors::function::{FnDescriptor},
descriptors::{
DescriptorDatabase,
module::{ModuleTree, Problem},
function::{FnDescriptor, FnId},
},
symbol_index::SymbolIndex,
syntax_ptr::SyntaxPtrDatabase,
CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position,
Query, SourceChange, SourceFileEdit, Cancelable,
};
@ -272,7 +275,7 @@ impl AnalysisImpl {
let syntax = file.syntax();
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
// First try to resolve the symbol locally
return if let Some((name, range)) = resolve_local_name(name_ref) {
return if let Some((name, range)) = resolve_local_name(&self.db, file_id, name_ref) {
let mut vec = vec![];
vec.push((
file_id,
@ -326,7 +329,7 @@ impl AnalysisImpl {
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
// We are only handing local references for now
if let Some(resolved) = resolve_local_name(name_ref) {
if let Some(resolved) = resolve_local_name(&self.db, file_id, name_ref) {
ret.push((file_id, resolved.1));
@ -334,7 +337,7 @@ impl AnalysisImpl {
let refs : Vec<_> = fn_def.syntax().descendants()
.filter_map(ast::NameRef::cast)
.filter(|&n: &ast::NameRef| resolve_local_name(n) == Some(resolved.clone()))
.filter(|&n: &ast::NameRef| resolve_local_name(&self.db, file_id, n) == Some(resolved.clone()))
.collect();
for r in refs {
@ -598,3 +601,16 @@ 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 fn_id = FnId::new(file_id, fn_def);
let scopes = db.fn_scopes(fn_id);
let scope_entry = crate::descriptors::function::resolve_local_name(name_ref, &scopes)?;
let syntax = db.resolve_syntax_ptr(scope_entry.ptr().into_global(file_id));
Some((scope_entry.name().clone(), syntax.range()))
}

View File

@ -84,6 +84,10 @@ impl LocalSyntaxPtr {
.unwrap_or_else(|| panic!("can't resovle local ptr to SyntaxNode: {:?}", self))
}
}
pub(crate) fn into_global(self, file_id: FileId) -> SyntaxPtr {
SyntaxPtr { file_id, local: self}
}
}

View File

@ -151,15 +151,7 @@ pub fn find_node_at_offset<'a, N: AstNode<'a>>(
leaf.ancestors().filter_map(N::cast).next()
}
pub fn resolve_local_name(
name_ref: ast::NameRef,
) -> Option<(SmolStr, TextRange)> {
let fn_def = name_ref.syntax().ancestors().find_map(ast::FnDef::cast)?;
let scopes = scope::FnScopes::new(fn_def);
let scope_entry = scope::resolve_local_name(name_ref, &scopes)?;
let name = scope_entry.ast().name()?;
Some((scope_entry.name(), name.syntax().range()))
}
#[cfg(test)]
mod tests {

View File

@ -258,22 +258,6 @@ struct ScopeData {
entries: Vec<ScopeEntry>,
}
pub fn resolve_local_name<'a>(
name_ref: ast::NameRef,
scopes: &'a FnScopes,
) -> Option<&'a ScopeEntry> {
use rustc_hash::FxHashSet;
let mut shadowed = FxHashSet::default();
let ret = scopes
.scope_chain(name_ref.syntax())
.flat_map(|scope| scopes.entries(scope).iter())
.filter(|entry| shadowed.insert(entry.name()))
.filter(|entry| entry.name() == name_ref.text())
.nth(0);
ret
}
#[cfg(test)]
mod tests {
use super::*;
@ -376,61 +360,4 @@ mod tests {
&["x"],
);
}
fn do_check_local_name(code: &str, expected_offset: u32) {
let (off, code) = extract_offset(code);
let file = File::parse(&code);
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 scopes = FnScopes::new(fn_def);
let local_name = resolve_local_name(name_ref, &scopes)
.unwrap()
.ast()
.name()
.unwrap();
let expected_name =
find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()).unwrap();
assert_eq!(local_name.syntax().range(), expected_name.syntax().range());
}
#[test]
fn test_resolve_local_name() {
do_check_local_name(
r#"
fn foo(x: i32, y: u32) {
{
let z = x * 2;
}
{
let t = x<|> * 3;
}
}"#,
21,
);
}
#[test]
fn test_resolve_local_name_declaration() {
do_check_local_name(
r#"
fn foo(x: String) {
let x : &str = &x<|>;
}"#,
21,
);
}
#[test]
fn test_resolve_local_name_shadow() {
do_check_local_name(
r"
fn foo(x: String) {
let x : &str = &x;
x<|>
}",
46,
);
}
}

View File

@ -2,6 +2,6 @@ mod fn_scope;
mod mod_scope;
pub use self::{
fn_scope::{resolve_local_name, FnScopes},
fn_scope::{FnScopes},
mod_scope::ModuleScope,
};