aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libanalysis/src/lib.rs')
-rw-r--r--crates/libanalysis/src/lib.rs47
1 files changed, 40 insertions, 7 deletions
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index e4df3de2e..f0d0cf0a4 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -6,6 +6,9 @@ extern crate log;
6extern crate once_cell; 6extern crate once_cell;
7extern crate libsyntax2; 7extern crate libsyntax2;
8extern crate libeditor; 8extern crate libeditor;
9extern crate fst;
10
11mod symbol_index;
9 12
10use once_cell::sync::OnceCell; 13use once_cell::sync::OnceCell;
11 14
@@ -14,8 +17,11 @@ use std::{
14 collections::hash_map::HashMap, 17 collections::hash_map::HashMap,
15 path::{PathBuf, Path}, 18 path::{PathBuf, Path},
16}; 19};
20
17use libsyntax2::ast; 21use libsyntax2::ast;
18use libeditor::LineIndex; 22use libeditor::{LineIndex, FileSymbol};
23
24use self::symbol_index::{FileSymbols, Query};
19 25
20pub type Result<T> = ::std::result::Result<T, ::failure::Error>; 26pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
21 27
@@ -70,12 +76,7 @@ impl WorldState {
70impl World { 76impl World {
71 pub fn file_syntax(&self, path: &Path) -> Result<ast::File> { 77 pub fn file_syntax(&self, path: &Path) -> Result<ast::File> {
72 let data = self.file_data(path)?; 78 let data = self.file_data(path)?;
73 let syntax = data.syntax 79 Ok(data.syntax(path).clone())
74 .get_or_init(|| {
75 trace!("parsing: {}", path.display());
76 ast::File::parse(&data.text)
77 }).clone();
78 Ok(syntax)
79 } 80 }
80 81
81 pub fn file_line_index(&self, path: &Path) -> Result<LineIndex> { 82 pub fn file_line_index(&self, path: &Path) -> Result<LineIndex> {
@@ -88,6 +89,16 @@ impl World {
88 Ok(index.clone()) 89 Ok(index.clone())
89 } 90 }
90 91
92 pub fn world_symbols(&self, query: &str, f: &mut FnMut(&Path, &FileSymbol) -> Search) {
93 let q = Query::new(query);
94 for (path, data) in self.data.file_map.iter() {
95 let symbols = data.symbols(path.as_path());
96 if q.process(symbols, &mut |symbol| f(path, symbol)) == Search::Break {
97 break;
98 }
99 }
100 }
101
91 fn file_data(&self, path: &Path) -> Result<Arc<FileData>> { 102 fn file_data(&self, path: &Path) -> Result<Arc<FileData>> {
92 match self.data.file_map.get(path) { 103 match self.data.file_map.get(path) {
93 Some(data) => Ok(data.clone()), 104 Some(data) => Ok(data.clone()),
@@ -96,6 +107,12 @@ impl World {
96 } 107 }
97} 108}
98 109
110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
111pub enum Search {
112 Continue,
113 Break,
114}
115
99 116
100#[derive(Default, Debug)] 117#[derive(Default, Debug)]
101struct WorldData { 118struct WorldData {
@@ -105,6 +122,7 @@ struct WorldData {
105#[derive(Debug)] 122#[derive(Debug)]
106struct FileData { 123struct FileData {
107 text: String, 124 text: String,
125 symbols: OnceCell<FileSymbols>,
108 syntax: OnceCell<ast::File>, 126 syntax: OnceCell<ast::File>,
109 lines: OnceCell<LineIndex>, 127 lines: OnceCell<LineIndex>,
110} 128}
@@ -113,8 +131,23 @@ impl FileData {
113 fn new(text: String) -> FileData { 131 fn new(text: String) -> FileData {
114 FileData { 132 FileData {
115 text, 133 text,
134 symbols: OnceCell::new(),
116 syntax: OnceCell::new(), 135 syntax: OnceCell::new(),
117 lines: OnceCell::new(), 136 lines: OnceCell::new(),
118 } 137 }
119 } 138 }
139
140 fn syntax(&self, path: &Path) -> &ast::File {
141 self.syntax
142 .get_or_init(|| {
143 trace!("parsing: {}", path.display());
144 ast::File::parse(&self.text)
145 })
146 }
147
148 fn symbols(&self, path: &Path) -> &FileSymbols {
149 let syntax = self.syntax(path);
150 self.symbols
151 .get_or_init(|| FileSymbols::new(syntax))
152 }
120} 153}