aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/symbol_index.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-09-16 10:54:24 +0100
committerAleksey Kladov <[email protected]>2018-09-16 11:07:39 +0100
commitb5021411a84822cb3f1e3aeffad9550dd15bdeb6 (patch)
tree9dca564f8e51b298dced01c4ce669c756dce3142 /crates/ra_analysis/src/symbol_index.rs
parentba0bfeee12e19da40b5eabc8d0408639af10e96f (diff)
rename all things
Diffstat (limited to 'crates/ra_analysis/src/symbol_index.rs')
-rw-r--r--crates/ra_analysis/src/symbol_index.rs94
1 files changed, 94 insertions, 0 deletions
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs
new file mode 100644
index 000000000..ffbb6a29f
--- /dev/null
+++ b/crates/ra_analysis/src/symbol_index.rs
@@ -0,0 +1,94 @@
1use std::{
2 sync::Arc,
3 hash::{Hash, Hasher},
4};
5use ra_editor::{FileSymbol, file_symbols};
6use ra_syntax::{
7 File,
8 SyntaxKind::{self, *},
9};
10use fst::{self, Streamer};
11use rayon::prelude::*;
12use {Query, FileId, JobToken};
13
14#[derive(Debug)]
15pub(crate) struct SymbolIndex {
16 symbols: Vec<(FileId, FileSymbol)>,
17 map: fst::Map,
18}
19
20impl Hash for SymbolIndex {
21 fn hash<H: Hasher>(&self, hasher: &mut H) {
22 self.symbols.hash(hasher)
23 }
24}
25
26impl SymbolIndex {
27 pub(crate) fn for_files(files: impl ParallelIterator<Item=(FileId, File)>) -> SymbolIndex {
28 let mut symbols = files
29 .flat_map(|(file_id, file)| {
30 file_symbols(&file)
31 .into_iter()
32 .map(move |symbol| {
33 (symbol.name.as_str().to_lowercase(), (file_id, symbol))
34 })
35 .collect::<Vec<_>>()
36 })
37 .collect::<Vec<_>>();
38 symbols.par_sort_by(|s1, s2| s1.0.cmp(&s2.0));
39 symbols.dedup_by(|s1, s2| s1.0 == s2.0);
40 let (names, symbols): (Vec<String>, Vec<(FileId, FileSymbol)>) =
41 symbols.into_iter().unzip();
42 let map = fst::Map::from_iter(
43 names.into_iter().zip(0u64..)
44 ).unwrap();
45 SymbolIndex { symbols, map }
46 }
47
48 pub(crate) fn for_file(file_id: FileId, file: File) -> SymbolIndex {
49 SymbolIndex::for_files(::rayon::iter::once((file_id, file)))
50 }
51}
52
53impl Query {
54 pub(crate) fn search(
55 self,
56 indices: &[Arc<SymbolIndex>],
57 token: &JobToken,
58 ) -> Vec<(FileId, FileSymbol)> {
59
60 let mut op = fst::map::OpBuilder::new();
61 for file_symbols in indices.iter() {
62 let automaton = fst::automaton::Subsequence::new(&self.lowercased);
63 op = op.add(file_symbols.map.search(automaton))
64 }
65 let mut stream = op.union();
66 let mut res = Vec::new();
67 while let Some((_, indexed_values)) = stream.next() {
68 if res.len() >= self.limit || token.is_canceled() {
69 break;
70 }
71 for indexed_value in indexed_values {
72 let file_symbols = &indices[indexed_value.index];
73 let idx = indexed_value.value as usize;
74
75 let (file_id, symbol) = &file_symbols.symbols[idx];
76 if self.only_types && !is_type(symbol.kind) {
77 continue;
78 }
79 if self.exact && symbol.name != self.query {
80 continue;
81 }
82 res.push((*file_id, symbol.clone()));
83 }
84 }
85 res
86 }
87}
88
89fn is_type(kind: SyntaxKind) -> bool {
90 match kind {
91 STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_DEF => true,
92 _ => false,
93 }
94}