From ebd7c04faa27564ca3f03eed6d4a3636b7d3fc4c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 3 Jan 2019 20:45:29 +0300 Subject: construct index from symbols directly --- crates/ra_analysis/Cargo.toml | 1 + crates/ra_analysis/src/symbol_index.rs | 29 ++++++++++++++++------------- 2 files changed, 17 insertions(+), 13 deletions(-) (limited to 'crates') diff --git a/crates/ra_analysis/Cargo.toml b/crates/ra_analysis/Cargo.toml index c0174cdc5..7a4fdaed9 100644 --- a/crates/ra_analysis/Cargo.toml +++ b/crates/ra_analysis/Cargo.toml @@ -13,6 +13,7 @@ fst = "0.3.1" salsa = "0.9.0" rustc-hash = "1.0" parking_lot = "0.7.0" +unicase = "2.2.0" ra_syntax = { path = "../ra_syntax" } ra_editor = { path = "../ra_editor" } diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs index b355b14ed..55caae5c2 100644 --- a/crates/ra_analysis/src/symbol_index.rs +++ b/crates/ra_analysis/src/symbol_index.rs @@ -20,6 +20,7 @@ //! file in the current workspace, and run a query aginst the union of all //! thouse fsts. use std::{ + cmp::Ordering, hash::{Hash, Hasher}, sync::Arc, }; @@ -111,6 +112,17 @@ impl Hash for SymbolIndex { } impl SymbolIndex { + fn new(mut symbols: Vec) -> SymbolIndex { + fn cmp(s1: &FileSymbol, s2: &FileSymbol) -> Ordering { + unicase::Ascii::new(s1.name.as_str()).cmp(&unicase::Ascii::new(s2.name.as_str())) + } + symbols.par_sort_by(cmp); + symbols.dedup_by(|s1, s2| cmp(s1, s2) == Ordering::Equal); + let names = symbols.iter().map(|it| it.name.as_str().to_lowercase()); + let map = fst::Map::from_iter(names.into_iter().zip(0u64..)).unwrap(); + SymbolIndex { symbols, map } + } + pub(crate) fn len(&self) -> usize { self.symbols.len() } @@ -118,28 +130,19 @@ impl SymbolIndex { pub(crate) fn for_files( files: impl ParallelIterator, ) -> SymbolIndex { - let mut symbols = files + let symbols = files .flat_map(|(file_id, file)| { file.syntax() .descendants() .filter_map(to_symbol) - .map(move |(name, ptr)| { - ( - name.as_str().to_lowercase(), - FileSymbol { name, ptr, file_id }, - ) - }) + .map(move |(name, ptr)| FileSymbol { name, ptr, file_id }) .collect::>() }) .collect::>(); - symbols.par_sort_by(|s1, s2| s1.0.cmp(&s2.0)); - symbols.dedup_by(|s1, s2| s1.0 == s2.0); - let (names, symbols): (Vec, Vec) = symbols.into_iter().unzip(); - let map = fst::Map::from_iter(names.into_iter().zip(0u64..)).unwrap(); - SymbolIndex { symbols, map } + SymbolIndex::new(symbols) } - pub(crate) fn for_file(file_id: FileId, file: SourceFileNode) -> SymbolIndex { + fn for_file(file_id: FileId, file: SourceFileNode) -> SymbolIndex { SymbolIndex::for_files(rayon::iter::once((file_id, file))) } } -- cgit v1.2.3 From d61707b4e1f0bdfc7f62b1abf78fdc45c0128699 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 3 Jan 2019 21:28:35 +0300 Subject: index stuff produced by macros --- crates/ra_analysis/src/symbol_index.rs | 29 ++++++++++++++++--------- crates/ra_analysis/tests/test/main.rs | 19 ++++++++++++++++- crates/ra_hir/src/ids.rs | 7 ++++++ crates/ra_hir/src/module/nameres.rs | 8 +++---- crates/ra_hir/src/source_binder.rs | 39 +++++++++++++++++++++++++++++++++- 5 files changed, 86 insertions(+), 16 deletions(-) (limited to 'crates') diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs index 55caae5c2..e2b1c88fe 100644 --- a/crates/ra_analysis/src/symbol_index.rs +++ b/crates/ra_analysis/src/symbol_index.rs @@ -28,11 +28,11 @@ use std::{ use fst::{self, Streamer}; use ra_syntax::{ SyntaxNodeRef, SourceFileNode, SmolStr, - algo::visit::{visitor, Visitor}, + algo::{visit::{visitor, Visitor}, find_covering_node}, SyntaxKind::{self, *}, ast::{self, NameOwner}, }; -use ra_db::{SyntaxDatabase, SourceRootId, FilesDatabase, LocalSyntaxPtr}; +use ra_db::{SourceRootId, FilesDatabase, LocalSyntaxPtr}; use salsa::ParallelDatabase; use rayon::prelude::*; @@ -42,7 +42,7 @@ use crate::{ }; salsa::query_group! { - pub(crate) trait SymbolsDatabase: SyntaxDatabase { + pub(crate) trait SymbolsDatabase: hir::db::HirDatabase { fn file_symbols(file_id: FileId) -> Cancelable> { type FileSymbolsQuery; } @@ -53,10 +53,23 @@ salsa::query_group! { } } -fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Cancelable> { +fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Cancelable> { db.check_canceled()?; - let syntax = db.source_file(file_id); - Ok(Arc::new(SymbolIndex::for_file(file_id, syntax))) + let source_file = db.source_file(file_id); + let mut symbols = source_file + .syntax() + .descendants() + .filter_map(to_symbol) + .map(move |(name, ptr)| FileSymbol { name, ptr, file_id }) + .collect::>(); + + for (name, text_range) in hir::source_binder::macro_symbols(db, file_id)? { + let node = find_covering_node(source_file.syntax(), text_range); + let ptr = LocalSyntaxPtr::new(node); + symbols.push(FileSymbol { file_id, name, ptr }) + } + + Ok(Arc::new(SymbolIndex::new(symbols))) } pub(crate) fn world_symbols(db: &RootDatabase, query: Query) -> Cancelable> { @@ -141,10 +154,6 @@ impl SymbolIndex { .collect::>(); SymbolIndex::new(symbols) } - - fn for_file(file_id: FileId, file: SourceFileNode) -> SymbolIndex { - SymbolIndex::for_files(rayon::iter::once((file_id, file))) - } } impl Query { diff --git a/crates/ra_analysis/tests/test/main.rs b/crates/ra_analysis/tests/test/main.rs index 23a5799b9..bfdf8aef2 100644 --- a/crates/ra_analysis/tests/test/main.rs +++ b/crates/ra_analysis/tests/test/main.rs @@ -6,7 +6,7 @@ use test_utils::{assert_eq_dbg, assert_eq_text}; use ra_analysis::{ mock_analysis::{analysis_and_position, single_file, single_file_with_position, MockAnalysis}, - AnalysisChange, CrateGraph, FileId, FnSignatureInfo, + AnalysisChange, CrateGraph, FileId, FnSignatureInfo, Query }; fn get_signature(text: &str) -> (FnSignatureInfo, Option) { @@ -531,6 +531,7 @@ fn test_rename_for_mut_param() { }"#, ); } + fn test_rename(text: &str, new_name: &str, expected: &str) { let (analysis, position) = single_file_with_position(text); let edits = analysis.rename(position, new_name).unwrap(); @@ -547,3 +548,19 @@ fn test_rename(text: &str, new_name: &str, expected: &str) { .apply(&*analysis.file_text(file_id.unwrap())); assert_eq_text!(expected, &*result); } + +#[test] +fn world_symbols_include_stuff_from_macros() { + let (analysis, _) = single_file( + " +salsa::query_group! { +pub trait HirDatabase: SyntaxDatabase {} +} + ", + ); + + let mut symbols = analysis.symbol_search(Query::new("Hir".into())).unwrap(); + let s = symbols.pop().unwrap(); + assert_eq!(s.name(), "HirDatabase"); + assert_eq!(s.range(), TextRange::from_to(33.into(), 44.into())); +} diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index a09dee8b1..4c7ebe3ea 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -48,6 +48,13 @@ impl HirFileId { } } + pub(crate) fn as_macro_call_id(self) -> Option { + match self.0 { + HirFileIdRepr::Macro(it) => Some(it), + _ => None, + } + } + pub(crate) fn hir_source_file(db: &impl HirDatabase, file_id: HirFileId) -> SourceFileNode { match file_id.0 { HirFileIdRepr::File(file_id) => db.source_file(file_id), diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index 40aa33ffa..8d1209626 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs @@ -64,14 +64,14 @@ impl ModuleScope { /// running name resolution. #[derive(Debug, Default, PartialEq, Eq)] pub struct InputModuleItems { - items: Vec, + pub(crate) items: Vec, imports: Vec, } #[derive(Debug, PartialEq, Eq)] -struct ModuleItem { - id: SourceItemId, - name: Name, +pub(crate) struct ModuleItem { + pub(crate) id: SourceItemId, + pub(crate) name: Name, kind: SyntaxKind, vis: Vis, } diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 24490d119..85bd84469 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -8,8 +8,8 @@ use ra_db::{FileId, FilePosition, Cancelable}; use ra_editor::find_node_at_offset; use ra_syntax::{ + SmolStr, TextRange, SyntaxNodeRef, ast::{self, AstNode, NameOwner}, - SyntaxNodeRef, }; use crate::{ @@ -126,3 +126,40 @@ pub fn function_from_child_node( let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast)); function_from_source(db, file_id, fn_def) } + +pub fn macro_symbols( + db: &impl HirDatabase, + file_id: FileId, +) -> Cancelable> { + let module = match module_from_file_id(db, file_id)? { + Some(it) => it, + None => return Ok(Vec::new()), + }; + let items = db.input_module_items(module.source_root_id, module.module_id)?; + let mut res = Vec::new(); + + for macro_call_id in items + .items + .iter() + .filter_map(|it| it.id.file_id.as_macro_call_id()) + { + if let Some(exp) = db.expand_macro_invocation(macro_call_id) { + let loc = macro_call_id.loc(db); + let syntax = db.file_item(loc.source_item_id); + let syntax = syntax.borrowed(); + let macro_call = ast::MacroCall::cast(syntax).unwrap(); + let off = macro_call.token_tree().unwrap().syntax().range().start(); + let file = exp.file(); + for trait_def in file.syntax().descendants().filter_map(ast::TraitDef::cast) { + if let Some(name) = trait_def.name() { + let dst_range = name.syntax().range(); + if let Some(src_range) = exp.map_range_back(dst_range) { + res.push((name.text(), src_range + off)) + } + } + } + } + } + + Ok(res) +} -- cgit v1.2.3