diff options
author | Aleksey Kladov <[email protected]> | 2018-08-13 14:07:05 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-13 14:07:05 +0100 |
commit | 7fc91f41d8bd948cef3085d7c0d0ec92d1b2bc53 (patch) | |
tree | d671181833c0af18fdfd167998cae1afbe759926 | |
parent | 0568e76406fc4869152671a255c5e1efca6611a6 (diff) |
Generalize query
-rw-r--r-- | crates/libanalysis/idx.rs | 84 | ||||
-rw-r--r-- | crates/libanalysis/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/libanalysis/src/symbol_index.rs | 56 | ||||
-rw-r--r-- | crates/server/src/main_loop/handlers.rs | 17 | ||||
-rw-r--r-- | crates/smol_str/src/lib.rs | 24 |
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 @@ | |||
1 | use std::path::PathBuf; | ||
2 | |||
3 | use fst; | ||
4 | use fst::IntoStreamer; | ||
5 | use file; | ||
6 | |||
7 | use fall_tree::{TextRange, NodeType}; | ||
8 | use indxr::{FileIndex, IndexableFileSet}; | ||
9 | |||
10 | use editor::line_index::{LineCol, LineIndex}; | ||
11 | use editor::fst_subseq::FstSubSeq; | ||
12 | use editor::file_symbols::process_symbols; | ||
13 | |||
14 | use syntax::{STRUCT_DEF, ENUM_DEF, TRAIT_DEF, TYPE_DEF}; | ||
15 | |||
16 | |||
17 | pub struct SymbolIndex { | ||
18 | index: FileIndex<FileSymbols>, | ||
19 | } | ||
20 | |||
21 | impl 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 | |||
52 | struct Query { | ||
53 | query: String, | ||
54 | all_symbols: bool, | ||
55 | } | ||
56 | |||
57 | impl 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::{ | |||
21 | use libsyntax2::ast; | 21 | use libsyntax2::ast; |
22 | use libeditor::{LineIndex, FileSymbol}; | 22 | use libeditor::{LineIndex, FileSymbol}; |
23 | 23 | ||
24 | use self::symbol_index::{FileSymbols, Query}; | 24 | use self::symbol_index::{FileSymbols}; |
25 | pub use self::symbol_index::Query; | ||
25 | 26 | ||
26 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; | 27 | pub 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 | }; |
6 | use fst::{self, IntoStreamer}; | 6 | use fst::{self, IntoStreamer, Streamer}; |
7 | 7 | ||
8 | #[derive(Debug)] | 8 | #[derive(Debug)] |
9 | pub(crate) struct FileSymbols { | 9 | pub(crate) struct FileSymbols { |
@@ -30,19 +30,30 @@ impl FileSymbols { | |||
30 | } | 30 | } |
31 | } | 31 | } |
32 | 32 | ||
33 | pub(crate) struct Query { | 33 | pub 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 | ||
38 | impl Query { | 40 | impl 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 | }; |
8 | use libanalysis::{World}; | 8 | use libanalysis::{World, Query}; |
9 | use libeditor; | 9 | use libeditor; |
10 | use libsyntax2::TextUnit; | 10 | use libsyntax2::TextUnit; |
11 | use serde_json::{to_value, from_value}; | 11 | use 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(¶ms.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 | ||
52 | impl PartialEq<String> for SmolStr { | ||
53 | fn eq(&self, other: &String) -> bool { | ||
54 | self.as_str() == other | ||
55 | } | ||
56 | } | ||
57 | |||
58 | impl PartialEq<SmolStr> for String { | ||
59 | fn eq(&self, other: &SmolStr) -> bool { | ||
60 | other == self | ||
61 | } | ||
62 | } | ||
63 | |||
64 | impl<'a> PartialEq<&'a String> for SmolStr { | ||
65 | fn eq(&self, other: &&'a String) -> bool { | ||
66 | self == *other | ||
67 | } | ||
68 | } | ||
69 | |||
70 | impl<'a> PartialEq<SmolStr> for &'a String { | ||
71 | fn eq(&self, other: &SmolStr) -> bool { | ||
72 | *self == other | ||
73 | } | ||
74 | } | ||
75 | |||
52 | impl fmt::Debug for SmolStr { | 76 | impl 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) |