Skip to content

Commit ce4b8c0

Browse files
feat: Parse whole workspace before sending rename and reference result (#61)
Closes #54
1 parent 68b3c2e commit ce4b8c0

File tree

4 files changed

+134
-89
lines changed

4 files changed

+134
-89
lines changed

src/lsp.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,23 @@ impl LanguageServer for ProtoLanguageServer {
228228
return Box::pin(async move { Ok(None) });
229229
};
230230

231+
let Some(workspace) = self.configs.get_workspace_for_uri(&uri) else {
232+
error!(uri=%uri, "failed to get workspace");
233+
return Box::pin(async move { Ok(None) });
234+
};
235+
236+
let work_done_token = params.work_done_progress_params.work_done_token;
237+
let progress_sender = work_done_token.map(|token| self.with_report_progress(token));
238+
231239
let mut h = HashMap::new();
232240
h.insert(tree.uri.clone(), edit);
233-
h.extend(self.state.rename_fields(current_package, &otext, &ntext));
241+
h.extend(self.state.rename_fields(
242+
current_package,
243+
&otext,
244+
&ntext,
245+
workspace.to_file_path().unwrap(),
246+
progress_sender,
247+
));
234248

235249
let response = Some(WorkspaceEdit {
236250
changes: Some(h),
@@ -246,6 +260,7 @@ impl LanguageServer for ProtoLanguageServer {
246260
) -> BoxFuture<'static, Result<Option<Vec<Location>>, ResponseError>> {
247261
let uri = param.text_document_position.text_document.uri;
248262
let pos = param.text_document_position.position;
263+
let work_done_token = param.work_done_progress_params.work_done_token;
249264

250265
let Some(tree) = self.state.get_tree(&uri) else {
251266
error!(uri=%uri, "failed to get tree");
@@ -264,7 +279,19 @@ impl LanguageServer for ProtoLanguageServer {
264279
return Box::pin(async move { Ok(None) });
265280
};
266281

267-
if let Some(v) = self.state.reference_fields(current_package, &otext) {
282+
let Some(workspace) = self.configs.get_workspace_for_uri(&uri) else {
283+
error!(uri=%uri, "failed to get workspace");
284+
return Box::pin(async move { Ok(None) });
285+
};
286+
287+
let progress_sender = work_done_token.map(|token| self.with_report_progress(token));
288+
289+
if let Some(v) = self.state.reference_fields(
290+
current_package,
291+
&otext,
292+
workspace.to_file_path().unwrap(),
293+
progress_sender,
294+
) {
268295
refs.extend(v);
269296
}
270297

src/server.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ impl ProtoLanguageServer {
3636
ControlFlow::Continue(())
3737
}
3838

39-
#[allow(unused)]
40-
fn with_report_progress(&self, token: NumberOrString) -> Sender<ProgressParamsValue> {
39+
pub fn with_report_progress(&self, token: NumberOrString) -> Sender<ProgressParamsValue> {
4140
let (tx, rx) = mpsc::channel();
4241
let mut socket = self.client.clone();
4342

src/state.rs

Lines changed: 64 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ use std::{
55
};
66
use tracing::info;
77

8+
use async_lsp::lsp_types::ProgressParamsValue;
89
use async_lsp::lsp_types::{CompletionItem, CompletionItemKind, PublishDiagnosticsParams, Url};
10+
use std::sync::mpsc::Sender;
911
use tree_sitter::Node;
12+
use walkdir::WalkDir;
1013

1114
use crate::{
1215
nodekind::NodeKind,
@@ -17,6 +20,7 @@ pub struct ProtoLanguageState {
1720
documents: Arc<RwLock<HashMap<Url, String>>>,
1821
trees: Arc<RwLock<HashMap<Url, ParsedTree>>>,
1922
parser: Arc<Mutex<ProtoParser>>,
23+
parsed_workspaces: Arc<RwLock<HashSet<String>>>,
2024
}
2125

2226
impl ProtoLanguageState {
@@ -25,6 +29,7 @@ impl ProtoLanguageState {
2529
documents: Default::default(),
2630
trees: Default::default(),
2731
parser: Arc::new(Mutex::new(ProtoParser::new())),
32+
parsed_workspaces: Arc::new(RwLock::new(HashSet::new())),
2833
}
2934
}
3035

@@ -146,83 +151,65 @@ impl ProtoLanguageState {
146151
.collect()
147152
}
148153

149-
// #[allow(unused)]
150-
// pub fn add_workspace_folder_async(
151-
// &mut self,
152-
// workspace: WorkspaceFolder,
153-
// tx: Sender<ProgressParamsValue>,
154-
// ) {
155-
// let parser = self.parser.clone();
156-
// let tree = self.trees.clone();
157-
// let docs = self.documents.clone();
158-
//
159-
// let begin = ProgressParamsValue::WorkDone(WorkDoneProgress::Begin(WorkDoneProgressBegin {
160-
// title: String::from("indexing"),
161-
// cancellable: Some(false),
162-
// percentage: Some(0),
163-
// ..Default::default()
164-
// }));
165-
//
166-
// if let Err(e) = tx.send(begin) {
167-
// error!(error=%e, "failed to send work begin progress");
168-
// }
169-
//
170-
// thread::spawn(move || {
171-
// let files: Vec<_> = WalkDir::new(workspace.uri.path())
172-
// .into_iter()
173-
// .filter_map(|e| e.ok())
174-
// .filter(|e| e.path().extension().is_some())
175-
// .filter(|e| e.path().extension().unwrap() == "proto")
176-
// .collect();
177-
//
178-
// let total_files = files.len();
179-
// let mut current = 0;
180-
//
181-
// for file in files.into_iter() {
182-
// let path = file.path();
183-
// if path.is_absolute() && path.is_file() {
184-
// let Ok(content) = read_to_string(path) else {
185-
// continue;
186-
// };
187-
//
188-
// let Ok(uri) = Url::from_file_path(path) else {
189-
// continue;
190-
// };
191-
//
192-
// Self::upsert_content_impl(
193-
// parser.lock().expect("poison"),
194-
// &uri,
195-
// content,
196-
// docs.write().expect("poison"),
197-
// tree.write().expect("poison"),
198-
// );
199-
//
200-
// current += 1;
201-
//
202-
// let report = ProgressParamsValue::WorkDone(WorkDoneProgress::Report(
203-
// WorkDoneProgressReport {
204-
// cancellable: Some(false),
205-
// message: Some(path.display().to_string()),
206-
// percentage: Some((current * 100 / total_files) as u32),
207-
// },
208-
// ));
209-
//
210-
// if let Err(e) = tx.send(report) {
211-
// error!(error=%e, "failed to send work report progress");
212-
// }
213-
// }
214-
// }
215-
// let report =
216-
// ProgressParamsValue::WorkDone(WorkDoneProgress::End(WorkDoneProgressEnd {
217-
// message: Some(String::from("completed")),
218-
// }));
219-
//
220-
// info!(len = total_files, "workspace file parsing completed");
221-
// if let Err(e) = tx.send(report) {
222-
// error!(error=%e, "failed to send work completed result");
223-
// }
224-
// });
225-
// }
154+
pub fn parse_all_from_workspace(
155+
&mut self,
156+
workspace: PathBuf,
157+
progress_sender: Option<Sender<ProgressParamsValue>>,
158+
) {
159+
if self
160+
.parsed_workspaces
161+
.read()
162+
.expect("poison")
163+
.contains(workspace.to_str().unwrap_or_default())
164+
{
165+
return;
166+
}
167+
168+
let files: Vec<_> = WalkDir::new(workspace.to_str().unwrap_or_default())
169+
.into_iter()
170+
.filter_map(|e| e.ok())
171+
.filter(|e| e.path().extension().is_some())
172+
.filter(|e| e.path().extension().unwrap() == "proto")
173+
.collect();
174+
175+
let total_files = files.len();
176+
177+
for (idx, file) in files.into_iter().enumerate() {
178+
let path = file.path();
179+
if path.is_absolute() && path.is_file() {
180+
if let Ok(content) = std::fs::read_to_string(path) {
181+
if let Ok(uri) = Url::from_file_path(path) {
182+
if self.documents.read().expect("poison").contains_key(&uri) {
183+
continue;
184+
}
185+
self.upsert_content(&uri, content, &[], 1);
186+
187+
if let Some(sender) = &progress_sender {
188+
let percentage = ((idx + 1) as f64 / total_files as f64 * 100.0) as u32;
189+
let _ = sender.send(ProgressParamsValue::WorkDone(
190+
async_lsp::lsp_types::WorkDoneProgress::Report(
191+
async_lsp::lsp_types::WorkDoneProgressReport {
192+
cancellable: None,
193+
message: Some(format!(
194+
"Parsing file {} of {}",
195+
idx + 1,
196+
total_files
197+
)),
198+
percentage: Some(percentage),
199+
},
200+
),
201+
));
202+
}
203+
}
204+
}
205+
}
206+
}
207+
208+
self.parsed_workspaces
209+
.write()
210+
.expect("poison")
211+
.insert(workspace.to_str().unwrap_or_default().to_string());
212+
}
226213

227214
pub fn upsert_file(
228215
&mut self,

src/workspace/rename.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
use crate::utils::split_identifier_package;
22
use std::collections::HashMap;
3+
use std::path::PathBuf;
34

45
use async_lsp::lsp_types::{Location, TextEdit, Url};
56

67
use crate::state::ProtoLanguageState;
8+
use async_lsp::lsp_types::ProgressParamsValue;
9+
use std::sync::mpsc::Sender;
710

811
impl ProtoLanguageState {
912
pub fn rename_fields(
10-
&self,
13+
&mut self,
1114
current_package: &str,
1215
identifier: &str,
1316
new_text: &str,
17+
workspace: PathBuf,
18+
progress_sender: Option<Sender<ProgressParamsValue>>,
1419
) -> HashMap<Url, Vec<TextEdit>> {
20+
self.parse_all_from_workspace(workspace, progress_sender);
1521
let (_, identifier) = split_identifier_package(identifier);
1622
self.get_trees()
1723
.into_iter()
@@ -33,10 +39,13 @@ impl ProtoLanguageState {
3339
}
3440

3541
pub fn reference_fields(
36-
&self,
42+
&mut self,
3743
current_package: &str,
3844
identifier: &str,
45+
workspace: PathBuf,
46+
progress_sender: Option<Sender<ProgressParamsValue>>,
3947
) -> Option<Vec<Location>> {
48+
self.parse_all_from_workspace(workspace, progress_sender);
4049
let (_, identifier) = split_identifier_package(identifier);
4150
let r = self
4251
.get_trees()
@@ -79,13 +88,27 @@ mod test {
7988
state.upsert_file(&b_uri, b.to_owned(), &ipath, 2);
8089
state.upsert_file(&c_uri, c.to_owned(), &ipath, 2);
8190

82-
assert_yaml_snapshot!(state.rename_fields("com.workspace", "Author", "Writer"));
91+
assert_yaml_snapshot!(state.rename_fields(
92+
"com.workspace",
93+
"Author",
94+
"Writer",
95+
PathBuf::from("src/workspace/input"),
96+
None
97+
));
8398
assert_yaml_snapshot!(state.rename_fields(
8499
"com.workspace",
85100
"Author.Address",
86-
"Author.Location"
101+
"Author.Location",
102+
PathBuf::from("src/workspace/input"),
103+
None
104+
));
105+
assert_yaml_snapshot!(state.rename_fields(
106+
"com.utility",
107+
"Foobar.Baz",
108+
"Foobar.Baaz",
109+
PathBuf::from("src/workspace/input"),
110+
None
87111
));
88-
assert_yaml_snapshot!(state.rename_fields("com.utility", "Foobar.Baz", "Foobar.Baaz"));
89112
}
90113

91114
#[test]
@@ -104,8 +127,17 @@ mod test {
104127
state.upsert_file(&b_uri, b.to_owned(), &ipath, 2);
105128
state.upsert_file(&c_uri, c.to_owned(), &ipath, 2);
106129

107-
assert_yaml_snapshot!(state.reference_fields("com.workspace", "Author"));
108-
assert_yaml_snapshot!(state.reference_fields("com.workspace", "Author.Address"));
109-
assert_yaml_snapshot!(state.reference_fields("com.utility", "Foobar.Baz"));
130+
assert_yaml_snapshot!(state.reference_fields(
131+
"com.workspace",
132+
"Author",
133+
PathBuf::from("src/workspace/input"),
134+
None
135+
));
136+
assert_yaml_snapshot!(state.reference_fields(
137+
"com.workspace",
138+
"Author.Address",
139+
PathBuf::from("src/workspace/input"),
140+
None
141+
));
110142
}
111143
}

0 commit comments

Comments
 (0)