aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-13 14:07:05 +0100
committerAleksey Kladov <[email protected]>2018-08-13 14:07:05 +0100
commit7fc91f41d8bd948cef3085d7c0d0ec92d1b2bc53 (patch)
treed671181833c0af18fdfd167998cae1afbe759926 /crates/libanalysis
parent0568e76406fc4869152671a255c5e1efca6611a6 (diff)
Generalize query
Diffstat (limited to 'crates/libanalysis')
-rw-r--r--crates/libanalysis/idx.rs84
-rw-r--r--crates/libanalysis/src/lib.rs8
-rw-r--r--crates/libanalysis/src/symbol_index.rs56
3 files changed, 40 insertions, 108 deletions
diff --git a/crates/libanalysis/idx.rs b/crates/libanalysis/idx.rs
deleted file mode 100644
index 69a635aef..000000000
--- a/crates/libanalysis/idx.rs
+++ /dev/null
@@ -1,84 +0,0 @@
1use std::path::PathBuf;
2
3use fst;
4use fst::IntoStreamer;
5use file;
6
7use fall_tree::{TextRange, NodeType};
8use indxr::{FileIndex, IndexableFileSet};
9
10use editor::line_index::{LineCol, LineIndex};
11use editor::fst_subseq::FstSubSeq;
12use editor::file_symbols::process_symbols;
13
14use syntax::{STRUCT_DEF, ENUM_DEF, TRAIT_DEF, TYPE_DEF};
15
16
17pub struct SymbolIndex {
18 index: FileIndex<FileSymbols>,
19}
20
21impl SymbolIndex {
22 pub fn new(roots: Vec<PathBuf>) -> SymbolIndex {
23 let file_set = IndexableFileSet::new(roots, "rs");
24 let index = FileIndex::new(file_set, Box::new(|path| {
25 let text = file::get_text(path).ok()?;
26 Some(FileSymbols::new(text))
27 }));
28 SymbolIndex { index }
29 }
30
31 pub fn query(&self, query: &str) -> Vec<(PathBuf, Symbol)> {
32 let mut query = Query::new(query);
33 let mut result = Vec::new();
34 self.process_query(&query, &mut result);
35 if result.is_empty() && !query.all_symbols {
36 query.all_symbols = true;
37 self.process_query(&query, &mut result);
38 }
39 result
40 }
41
42 fn process_query(&self, query: &Query, acc: &mut Vec<(PathBuf, Symbol)>) {
43 self.index.process_files(&mut |file| {
44 query.process(&file.value, &mut |symbol| {
45 acc.push((file.path.clone(), symbol))
46 });
47 acc.len() > 512
48 });
49 }
50}
51
52struct Query {
53 query: String,
54 all_symbols: bool,
55}
56
57impl Query {
58 fn new(query: &str) -> Query {
59 let all_symbols = query.contains("#");
60 let query: String = query.chars()
61 .filter(|&c| c != '#')
62 .flat_map(char::to_lowercase)
63 .collect();
64 Query { query, all_symbols }
65 }
66
67 fn process(&self, file: &FileSymbols, acc: &mut FnMut(Symbol)) {
68 fn is_type(ty: NodeType) -> bool {
69 match ty {
70 STRUCT_DEF | ENUM_DEF | TRAIT_DEF| TYPE_DEF => true,
71 _ => false,
72 }
73 }
74
75 let a = FstSubSeq::new(&self.query);
76 for idx in file.map.search(a).into_stream().into_values() {
77 let idx = idx as usize;
78 let symbol = file.symbols[idx].clone();
79 if self.all_symbols || is_type(symbol.ty) {
80 acc(symbol)
81 }
82 }
83 }
84}
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index acaadb8a2..b2f4bdbb3 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -21,7 +21,8 @@ use std::{
21use libsyntax2::ast; 21use libsyntax2::ast;
22use libeditor::{LineIndex, FileSymbol}; 22use libeditor::{LineIndex, FileSymbol};
23 23
24use self::symbol_index::{FileSymbols, Query}; 24use self::symbol_index::{FileSymbols};
25pub use self::symbol_index::Query;
25 26
26pub type Result<T> = ::std::result::Result<T, ::failure::Error>; 27pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
27 28
@@ -89,14 +90,13 @@ impl World {
89 Ok(index.clone()) 90 Ok(index.clone())
90 } 91 }
91 92
92 pub fn world_symbols<'a>(&'a self, query: &str) -> impl Iterator<Item=(&'a Path, &'a FileSymbol)> + 'a 93 pub fn world_symbols<'a>(&'a self, query: Query) -> impl Iterator<Item=(&'a Path, &'a FileSymbol)> + 'a
93 { 94 {
94 let q = Query::new(query);
95 self.data.file_map.iter() 95 self.data.file_map.iter()
96 .flat_map(move |(path, data)| { 96 .flat_map(move |(path, data)| {
97 let path: &'a Path = path.as_path(); 97 let path: &'a Path = path.as_path();
98 let symbols = data.symbols(path); 98 let symbols = data.symbols(path);
99 q.process(symbols).map(move |s| (path, s)) 99 query.process(symbols).map(move |s| (path, s))
100 }) 100 })
101 } 101 }
102 102
diff --git a/crates/libanalysis/src/symbol_index.rs b/crates/libanalysis/src/symbol_index.rs
index 4d90aac0c..88d5c4995 100644
--- a/crates/libanalysis/src/symbol_index.rs
+++ b/crates/libanalysis/src/symbol_index.rs
@@ -3,7 +3,7 @@ use libsyntax2::{
3 ast, 3 ast,
4 SyntaxKind::{self, *}, 4 SyntaxKind::{self, *},
5}; 5};
6use fst::{self, IntoStreamer}; 6use fst::{self, IntoStreamer, Streamer};
7 7
8#[derive(Debug)] 8#[derive(Debug)]
9pub(crate) struct FileSymbols { 9pub(crate) struct FileSymbols {
@@ -30,19 +30,30 @@ impl FileSymbols {
30 } 30 }
31} 31}
32 32
33pub(crate) struct Query { 33pub struct Query {
34 query: String, 34 query: String,
35 all_symbols: bool, 35 lowercased: String,
36 only_types: bool,
37 exact: bool,
36} 38}
37 39
38impl Query { 40impl Query {
39 pub(crate) fn new(query: &str) -> Query { 41 pub fn new(query: String) -> Query {
40 let all_symbols = query.contains("#"); 42 let lowercased = query.to_lowercase();
41 let query: String = query.chars() 43 Query {
42 .filter(|&c| c != '#') 44 query,
43 .flat_map(char::to_lowercase) 45 lowercased,
44 .collect(); 46 only_types: false,
45 Query { query, all_symbols } 47 exact: false,
48 }
49 }
50
51 pub fn only_types(&mut self) {
52 self.only_types = true;
53 }
54
55 pub fn exact(&mut self) {
56 self.exact = true;
46 } 57 }
47 58
48 pub(crate) fn process<'a>( 59 pub(crate) fn process<'a>(
@@ -55,16 +66,21 @@ impl Query {
55 _ => false, 66 _ => false,
56 } 67 }
57 } 68 }
58 let automaton = fst::automaton::Subsequence::new(&self.query); 69 let automaton = fst::automaton::Subsequence::new(&self.lowercased);
59 let all_symbols = self.all_symbols; 70 let mut stream = file.map.search(automaton).into_stream();
60 file.map.search(automaton).into_stream() 71 let mut res = Vec::new();
61 .into_values() 72 while let Some((_, idx)) = stream.next() {
62 .into_iter() 73 let idx = idx as usize;
63 .map(move |idx| { 74 let symbol = &file.symbols[idx];
64 let idx = idx as usize; 75 if self.only_types && !is_type(symbol.kind) {
65 &file.symbols[idx] 76 continue;
66 }) 77 }
67 .filter(move |s| all_symbols || is_type(s.kind)) 78 if self.exact && symbol.name != self.query {
79 continue;
80 }
81 res.push(symbol)
82 }
83 res.into_iter()
68 } 84 }
69} 85}
70 86