aboutsummaryrefslogtreecommitdiff
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
parent0568e76406fc4869152671a255c5e1efca6611a6 (diff)
Generalize query
-rw-r--r--crates/libanalysis/idx.rs84
-rw-r--r--crates/libanalysis/src/lib.rs8
-rw-r--r--crates/libanalysis/src/symbol_index.rs56
-rw-r--r--crates/server/src/main_loop/handlers.rs17
-rw-r--r--crates/smol_str/src/lib.rs24
5 files changed, 79 insertions, 110 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
diff --git a/crates/server/src/main_loop/handlers.rs b/crates/server/src/main_loop/handlers.rs
index bd0e6825b..f51909280 100644
--- a/crates/server/src/main_loop/handlers.rs
+++ b/crates/server/src/main_loop/handlers.rs
@@ -5,7 +5,7 @@ use languageserver_types::{
5 Command, TextDocumentIdentifier, WorkspaceEdit, 5 Command, TextDocumentIdentifier, WorkspaceEdit,
6 SymbolInformation, Location, 6 SymbolInformation, Location,
7}; 7};
8use libanalysis::{World}; 8use libanalysis::{World, Query};
9use libeditor; 9use libeditor;
10use libsyntax2::TextUnit; 10use libsyntax2::TextUnit;
11use serde_json::{to_value, from_value}; 11use serde_json::{to_value, from_value};
@@ -100,7 +100,20 @@ pub fn handle_workspace_symbol(
100 params: req::WorkspaceSymbolParams, 100 params: req::WorkspaceSymbolParams,
101) -> Result<Option<Vec<SymbolInformation>>> { 101) -> Result<Option<Vec<SymbolInformation>>> {
102 let mut acc = Vec::new(); 102 let mut acc = Vec::new();
103 for (path, symbol) in world.world_symbols(&params.query).take(128) { 103
104 let query = {
105 let all_symbols = params.query.contains("#");
106 let query: String = params.query.chars()
107 .filter(|&c| c != '#')
108 .collect();
109 let mut q = Query::new(query);
110 if !all_symbols {
111 q.only_types();
112 }
113 q
114 };
115
116 for (path, symbol) in world.world_symbols(query).take(128) {
104 let line_index = world.file_line_index(path)?; 117 let line_index = world.file_line_index(path)?;
105 118
106 let info = SymbolInformation { 119 let info = SymbolInformation {
diff --git a/crates/smol_str/src/lib.rs b/crates/smol_str/src/lib.rs
index 41c3a39ef..79b179ef4 100644
--- a/crates/smol_str/src/lib.rs
+++ b/crates/smol_str/src/lib.rs
@@ -49,6 +49,30 @@ impl<'a> PartialEq<SmolStr> for &'a str {
49 } 49 }
50} 50}
51 51
52impl PartialEq<String> for SmolStr {
53 fn eq(&self, other: &String) -> bool {
54 self.as_str() == other
55 }
56}
57
58impl PartialEq<SmolStr> for String {
59 fn eq(&self, other: &SmolStr) -> bool {
60 other == self
61 }
62}
63
64impl<'a> PartialEq<&'a String> for SmolStr {
65 fn eq(&self, other: &&'a String) -> bool {
66 self == *other
67 }
68}
69
70impl<'a> PartialEq<SmolStr> for &'a String {
71 fn eq(&self, other: &SmolStr) -> bool {
72 *self == other
73 }
74}
75
52impl fmt::Debug for SmolStr { 76impl fmt::Debug for SmolStr {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 77 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 fmt::Debug::fmt(self.as_str(), f) 78 fmt::Debug::fmt(self.as_str(), f)