mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
move resolve local name
This commit is contained in:
parent
b67295134b
commit
c02be1502c
7 changed files with 31 additions and 94 deletions
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
syntax_ptr::SyntaxPtr
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
algo::generate,
|
algo::generate,
|
||||||
|
@ -261,8 +261,6 @@ pub fn resolve_local_name<'a>(
|
||||||
name_ref: ast::NameRef,
|
name_ref: ast::NameRef,
|
||||||
scopes: &'a FnScopes,
|
scopes: &'a FnScopes,
|
||||||
) -> Option<&'a ScopeEntry> {
|
) -> Option<&'a ScopeEntry> {
|
||||||
use rustc_hash::FxHashSet;
|
|
||||||
|
|
||||||
let mut shadowed = FxHashSet::default();
|
let mut shadowed = FxHashSet::default();
|
||||||
let ret = scopes
|
let ret = scopes
|
||||||
.scope_chain(name_ref.syntax())
|
.scope_chain(name_ref.syntax())
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::{
|
||||||
sync::Arc,
|
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::{
|
use ra_syntax::{
|
||||||
ast::{self, ArgListOwner, Expr, NameOwner},
|
ast::{self, ArgListOwner, Expr, NameOwner},
|
||||||
AstNode, File, SmolStr,
|
AstNode, File, SmolStr,
|
||||||
|
@ -21,10 +21,13 @@ use crate::{
|
||||||
self, SyntaxDatabase, FileSyntaxQuery,
|
self, SyntaxDatabase, FileSyntaxQuery,
|
||||||
},
|
},
|
||||||
input::{SourceRootId, FilesDatabase, SourceRoot, WORKSPACE},
|
input::{SourceRootId, FilesDatabase, SourceRoot, WORKSPACE},
|
||||||
descriptors::DescriptorDatabase,
|
descriptors::{
|
||||||
descriptors::module::{ModuleTree, Problem},
|
DescriptorDatabase,
|
||||||
descriptors::function::{FnDescriptor},
|
module::{ModuleTree, Problem},
|
||||||
|
function::{FnDescriptor, FnId},
|
||||||
|
},
|
||||||
symbol_index::SymbolIndex,
|
symbol_index::SymbolIndex,
|
||||||
|
syntax_ptr::SyntaxPtrDatabase,
|
||||||
CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position,
|
CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position,
|
||||||
Query, SourceChange, SourceFileEdit, Cancelable,
|
Query, SourceChange, SourceFileEdit, Cancelable,
|
||||||
};
|
};
|
||||||
|
@ -272,7 +275,7 @@ impl AnalysisImpl {
|
||||||
let syntax = file.syntax();
|
let syntax = file.syntax();
|
||||||
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
|
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
|
||||||
// First try to resolve the symbol locally
|
// 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![];
|
let mut vec = vec![];
|
||||||
vec.push((
|
vec.push((
|
||||||
file_id,
|
file_id,
|
||||||
|
@ -326,7 +329,7 @@ impl AnalysisImpl {
|
||||||
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
|
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
|
||||||
|
|
||||||
// We are only handing local references for now
|
// 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));
|
ret.push((file_id, resolved.1));
|
||||||
|
|
||||||
|
@ -334,7 +337,7 @@ impl AnalysisImpl {
|
||||||
|
|
||||||
let refs : Vec<_> = fn_def.syntax().descendants()
|
let refs : Vec<_> = fn_def.syntax().descendants()
|
||||||
.filter_map(ast::NameRef::cast)
|
.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();
|
.collect();
|
||||||
|
|
||||||
for r in refs {
|
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()))
|
||||||
|
}
|
||||||
|
|
|
@ -84,6 +84,10 @@ impl LocalSyntaxPtr {
|
||||||
.unwrap_or_else(|| panic!("can't resovle local ptr to SyntaxNode: {:?}", self))
|
.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}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -151,15 +151,7 @@ pub fn find_node_at_offset<'a, N: AstNode<'a>>(
|
||||||
leaf.ancestors().filter_map(N::cast).next()
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -258,22 +258,6 @@ struct ScopeData {
|
||||||
entries: Vec<ScopeEntry>,
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -376,61 +360,4 @@ mod tests {
|
||||||
&["x"],
|
&["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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@ mod fn_scope;
|
||||||
mod mod_scope;
|
mod mod_scope;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
fn_scope::{resolve_local_name, FnScopes},
|
fn_scope::{FnScopes},
|
||||||
mod_scope::ModuleScope,
|
mod_scope::ModuleScope,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue