mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 01:17:27 +00:00
Implement Find All References for local variables
This commit is contained in:
parent
2a704035f4
commit
3746689e9d
8 changed files with 96 additions and 3 deletions
|
@ -257,6 +257,38 @@ impl AnalysisImpl {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_all_refs(&self, file_id: FileId, offset: TextUnit, _token: &JobToken) -> Vec<(FileId, TextRange)> {
|
||||||
|
let root = self.root(file_id);
|
||||||
|
let file = root.syntax(file_id);
|
||||||
|
let syntax = file.syntax();
|
||||||
|
|
||||||
|
let mut ret = vec![];
|
||||||
|
|
||||||
|
// Find the symbol we are looking for
|
||||||
|
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(&file, offset, name_ref) {
|
||||||
|
|
||||||
|
ret.push((file_id, resolved.1));
|
||||||
|
|
||||||
|
if let Some(fn_def) = find_node_at_offset::<ast::FnDef>(syntax, offset) {
|
||||||
|
|
||||||
|
let refs : Vec<_> = fn_def.syntax().descendants()
|
||||||
|
.filter_map(ast::NameRef::cast)
|
||||||
|
.filter(|n: &ast::NameRef| resolve_local_name(&file, n.syntax().range().start(), *n) == Some(resolved.clone()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for r in refs {
|
||||||
|
ret.push((file_id, r.syntax().range()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> {
|
pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> {
|
||||||
let root = self.root(file_id);
|
let root = self.root(file_id);
|
||||||
let module_tree = root.module_tree();
|
let module_tree = root.module_tree();
|
||||||
|
|
|
@ -217,6 +217,9 @@ impl Analysis {
|
||||||
self.imp
|
self.imp
|
||||||
.approximately_resolve_symbol(file_id, offset, token)
|
.approximately_resolve_symbol(file_id, offset, token)
|
||||||
}
|
}
|
||||||
|
pub fn find_all_refs(&self, file_id: FileId, offset: TextUnit, token: &JobToken) -> Vec<(FileId, TextRange)> {
|
||||||
|
self.imp.find_all_refs(file_id, offset, token)
|
||||||
|
}
|
||||||
pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> {
|
pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> {
|
||||||
self.imp.parent_module(file_id)
|
self.imp.parent_module(file_id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ use std::sync::Arc;
|
||||||
use ra_analysis::{
|
use ra_analysis::{
|
||||||
Analysis, AnalysisHost, CrateGraph, CrateId, FileId, FileResolver, FnDescriptor, JobHandle,
|
Analysis, AnalysisHost, CrateGraph, CrateId, FileId, FileResolver, FnDescriptor, JobHandle,
|
||||||
};
|
};
|
||||||
|
use ra_syntax::TextRange;
|
||||||
|
|
||||||
use relative_path::{RelativePath, RelativePathBuf};
|
use relative_path::{RelativePath, RelativePathBuf};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use test_utils::{assert_eq_dbg, extract_offset};
|
use test_utils::{assert_eq_dbg, extract_offset};
|
||||||
|
@ -225,3 +227,43 @@ fn bar() {
|
||||||
assert_eq!(desc.ret_type, None);
|
assert_eq!(desc.ret_type, None);
|
||||||
assert_eq!(param, Some(1));
|
assert_eq!(param, Some(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_all_refs(text: &str) -> Vec<(FileId, TextRange)> {
|
||||||
|
let (offset, code) = extract_offset(text);
|
||||||
|
let code = code.as_str();
|
||||||
|
|
||||||
|
let (_handle, token) = JobHandle::new();
|
||||||
|
let snap = analysis(&[("/lib.rs", code)]);
|
||||||
|
|
||||||
|
snap.find_all_refs(FileId(1), offset, &token)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_find_all_refs_for_local() {
|
||||||
|
let code = r#"
|
||||||
|
fn main() {
|
||||||
|
let mut i = 1;
|
||||||
|
let j = 1;
|
||||||
|
i = i<|> + j;
|
||||||
|
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 5;
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
let refs = get_all_refs(code);
|
||||||
|
assert_eq!(refs.len(), 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_find_all_refs_for_param_inside() {
|
||||||
|
let code = r#"
|
||||||
|
fn foo(i : u32) -> u32 {
|
||||||
|
i<|>
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
let refs = get_all_refs(code);
|
||||||
|
assert_eq!(refs.len(), 2);
|
||||||
|
}
|
|
@ -270,7 +270,6 @@ pub fn resolve_local_name<'a>(
|
||||||
.filter(|entry| shadowed.insert(entry.name()))
|
.filter(|entry| shadowed.insert(entry.name()))
|
||||||
.filter(|entry| entry.name() == name_ref.text())
|
.filter(|entry| entry.name() == name_ref.text())
|
||||||
.nth(0);
|
.nth(0);
|
||||||
eprintln!("ret = {:?}", ret);
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub fn server_capabilities() -> ServerCapabilities {
|
||||||
definition_provider: Some(true),
|
definition_provider: Some(true),
|
||||||
type_definition_provider: None,
|
type_definition_provider: None,
|
||||||
implementation_provider: None,
|
implementation_provider: None,
|
||||||
references_provider: None,
|
references_provider: Some(true),
|
||||||
document_highlight_provider: None,
|
document_highlight_provider: None,
|
||||||
document_symbol_provider: Some(true),
|
document_symbol_provider: Some(true),
|
||||||
workspace_symbol_provider: Some(true),
|
workspace_symbol_provider: Some(true),
|
||||||
|
|
|
@ -460,6 +460,22 @@ pub fn handle_signature_help(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_references(
|
||||||
|
world: ServerWorld,
|
||||||
|
params: req::ReferenceParams,
|
||||||
|
token: JobToken,
|
||||||
|
) -> Result<Option<Vec<Location>>> {
|
||||||
|
let file_id = params.text_document.try_conv_with(&world)?;
|
||||||
|
let line_index = world.analysis().file_line_index(file_id);
|
||||||
|
let offset = params.position.conv_with(&line_index);
|
||||||
|
|
||||||
|
let refs = world.analysis().find_all_refs(file_id, offset, &token);
|
||||||
|
|
||||||
|
Ok(Some(refs.into_iter()
|
||||||
|
.filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok())
|
||||||
|
.collect()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_code_action(
|
pub fn handle_code_action(
|
||||||
world: ServerWorld,
|
world: ServerWorld,
|
||||||
params: req::CodeActionParams,
|
params: req::CodeActionParams,
|
||||||
|
|
|
@ -248,6 +248,7 @@ fn on_request(
|
||||||
.on::<req::CodeActionRequest>(handlers::handle_code_action)?
|
.on::<req::CodeActionRequest>(handlers::handle_code_action)?
|
||||||
.on::<req::FoldingRangeRequest>(handlers::handle_folding_range)?
|
.on::<req::FoldingRangeRequest>(handlers::handle_folding_range)?
|
||||||
.on::<req::SignatureHelpRequest>(handlers::handle_signature_help)?
|
.on::<req::SignatureHelpRequest>(handlers::handle_signature_help)?
|
||||||
|
.on::<req::References>(handlers::handle_references)?
|
||||||
.finish();
|
.finish();
|
||||||
match req {
|
match req {
|
||||||
Ok((id, handle)) => {
|
Ok((id, handle)) => {
|
||||||
|
|
|
@ -7,7 +7,7 @@ pub use languageserver_types::{
|
||||||
CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams,
|
CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams,
|
||||||
DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult,
|
DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult,
|
||||||
PublishDiagnosticsParams, SignatureHelp, TextDocumentEdit, TextDocumentPositionParams,
|
PublishDiagnosticsParams, SignatureHelp, TextDocumentEdit, TextDocumentPositionParams,
|
||||||
TextEdit, WorkspaceSymbolParams,
|
TextEdit, WorkspaceSymbolParams, ReferenceParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum SyntaxTree {}
|
pub enum SyntaxTree {}
|
||||||
|
|
Loading…
Reference in a new issue