2018-08-13 15:10:20 +03:00
|
|
|
use libeditor::{FileSymbol, file_symbols};
|
|
|
|
|
use libsyntax2::{
|
2018-08-25 11:44:58 +03:00
|
|
|
File,
|
2018-08-13 15:10:20 +03:00
|
|
|
SyntaxKind::{self, *},
|
|
|
|
|
};
|
2018-09-02 20:08:58 +03:00
|
|
|
use fst::{self, Streamer};
|
|
|
|
|
use {Query, FileId, JobToken};
|
2018-08-13 15:10:20 +03:00
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub(crate) struct FileSymbols {
|
2018-09-02 23:36:23 +03:00
|
|
|
symbols: Vec<(FileId, FileSymbol)>,
|
2018-08-13 15:10:20 +03:00
|
|
|
map: fst::Map,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl FileSymbols {
|
2018-09-02 23:36:23 +03:00
|
|
|
pub(crate) fn new(file_id: FileId, file: &File) -> FileSymbols {
|
2018-08-13 15:10:20 +03:00
|
|
|
let mut symbols = file_symbols(file)
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|s| (s.name.as_str().to_lowercase(), s))
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
|
|
symbols.sort_by(|s1, s2| s1.0.cmp(&s2.0));
|
|
|
|
|
symbols.dedup_by(|s1, s2| s1.0 == s2.0);
|
2018-09-02 23:36:23 +03:00
|
|
|
let (names, symbols): (Vec<String>, Vec<(FileId, FileSymbol)>) =
|
|
|
|
|
symbols.into_iter()
|
|
|
|
|
.map(|(name, symbol)| (name, (file_id, symbol)))
|
|
|
|
|
.unzip();
|
2018-08-13 15:10:20 +03:00
|
|
|
|
|
|
|
|
let map = fst::Map::from_iter(
|
|
|
|
|
names.into_iter().zip(0u64..)
|
|
|
|
|
).unwrap();
|
|
|
|
|
FileSymbols { symbols, map }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Query {
|
2018-09-02 20:08:58 +03:00
|
|
|
pub(crate) fn search(
|
|
|
|
|
mut self,
|
2018-09-02 23:36:23 +03:00
|
|
|
indices: &[&FileSymbols],
|
2018-09-02 20:08:58 +03:00
|
|
|
token: &JobToken,
|
|
|
|
|
) -> Vec<(FileId, FileSymbol)> {
|
|
|
|
|
|
|
|
|
|
let mut op = fst::map::OpBuilder::new();
|
2018-09-02 23:36:23 +03:00
|
|
|
for file_symbols in indices.iter() {
|
2018-09-02 20:08:58 +03:00
|
|
|
let automaton = fst::automaton::Subsequence::new(&self.lowercased);
|
|
|
|
|
op = op.add(file_symbols.map.search(automaton))
|
2018-08-13 15:10:20 +03:00
|
|
|
}
|
2018-09-02 20:08:58 +03:00
|
|
|
let mut stream = op.union();
|
2018-08-13 16:07:05 +03:00
|
|
|
let mut res = Vec::new();
|
2018-09-02 20:08:58 +03:00
|
|
|
while let Some((_, indexed_values)) = stream.next() {
|
|
|
|
|
if self.limit == 0 || token.is_canceled() {
|
2018-08-13 17:19:27 +03:00
|
|
|
break;
|
|
|
|
|
}
|
2018-09-02 20:08:58 +03:00
|
|
|
for indexed_value in indexed_values {
|
2018-09-02 23:36:23 +03:00
|
|
|
let file_symbols = &indices[indexed_value.index];
|
2018-09-02 20:08:58 +03:00
|
|
|
let idx = indexed_value.value as usize;
|
|
|
|
|
|
2018-09-02 23:36:23 +03:00
|
|
|
let (file_id, symbol) = &file_symbols.symbols[idx];
|
2018-09-02 20:08:58 +03:00
|
|
|
if self.only_types && !is_type(symbol.kind) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if self.exact && symbol.name != self.query {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
res.push((*file_id, symbol.clone()));
|
|
|
|
|
self.limit -= 1;
|
2018-08-13 16:07:05 +03:00
|
|
|
}
|
|
|
|
|
}
|
2018-08-13 17:19:27 +03:00
|
|
|
res
|
2018-08-13 15:10:20 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-02 20:08:58 +03:00
|
|
|
fn is_type(kind: SyntaxKind) -> bool {
|
|
|
|
|
match kind {
|
|
|
|
|
STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_DEF => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
}
|
|
|
|
|
}
|