Skip to content

Commit 98d7869

Browse files
committed
refactor(language_server): store serde_json::Value for WorkspaceWorker option (#15280)
> This PR refactors the `WorkspaceWorker` to store client options as raw serde_json::Value instead of deserialized Options struct. Later the `serde_json::Value` should pass to each individual tool
1 parent 2fd43b4 commit 98d7869

File tree

1 file changed

+31
-22
lines changed

1 file changed

+31
-22
lines changed

crates/oxc_language_server/src/worker.rs

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ pub struct WorkspaceWorker {
3030
root_uri: Uri,
3131
server_linter: RwLock<Option<ServerLinter>>,
3232
server_formatter: RwLock<Option<ServerFormatter>>,
33-
options: Mutex<Option<Options>>,
33+
// Initialized options from the client
34+
// If None, the worker has not been initialized yet
35+
options: Mutex<Option<serde_json::Value>>,
3436
}
3537

3638
impl WorkspaceWorker {
@@ -69,8 +71,8 @@ impl WorkspaceWorker {
6971
/// Start all programs (linter, formatter) for the worker.
7072
/// This should be called after the client has sent the workspace configuration.
7173
pub async fn start_worker(&self, options: &serde_json::Value) {
72-
let options = serde_json::from_value::<Options>(options.clone()).unwrap_or_default();
7374
*self.options.lock().await = Some(options.clone());
75+
let options = serde_json::from_value::<Options>(options.clone()).unwrap_or_default();
7476

7577
*self.server_linter.write().await = Some(ServerLinter::new(&self.root_uri, &options.lint));
7678
if options.format.experimental {
@@ -91,21 +93,23 @@ impl WorkspaceWorker {
9193
};
9294

9395
// clone the options to avoid locking the mutex
94-
let options = self.options.lock().await;
95-
let lint_options = options.as_ref().map(|o| o.lint.clone()).unwrap_or_default();
96-
let format_options = options.as_ref().map(|o| o.format.clone()).unwrap_or_default();
96+
let options = {
97+
let options = self.options.lock().await;
98+
serde_json::from_value::<Options>(options.clone().unwrap_or_default())
99+
.unwrap_or_default()
100+
};
97101
let lint_patterns = self
98102
.server_linter
99103
.read()
100104
.await
101105
.as_ref()
102-
.map(|linter| linter.get_watch_patterns(&lint_options, root_path));
106+
.map(|linter| linter.get_watch_patterns(&options.lint, root_path));
103107
let format_patterns = self
104108
.server_formatter
105109
.read()
106110
.await
107111
.as_ref()
108-
.map(|formatter| formatter.get_watcher_patterns(&format_options));
112+
.map(|formatter| formatter.get_watcher_patterns(&options.format));
109113

110114
if let Some(lint_patterns) = lint_patterns {
111115
registrations.push(Registration {
@@ -126,7 +130,7 @@ impl WorkspaceWorker {
126130
});
127131
}
128132

129-
if format_options.experimental
133+
if options.format.experimental
130134
&& let Some(format_patterns) = format_patterns
131135
{
132136
registrations.push(Registration {
@@ -189,7 +193,10 @@ impl WorkspaceWorker {
189193
/// Check if the linter should run for the given run type
190194
/// This compares the current run level from the options with the given run type
191195
pub async fn should_lint_on_run_type(&self, current_run: Run) -> bool {
192-
let run_level = { self.options.lock().await.as_ref().map(|o| o.lint.run) };
196+
let options = self.options.lock().await;
197+
let run_level = options.as_ref().and_then(|o| {
198+
serde_json::from_value::<Options>(o.clone()).ok().map(|opts| opts.lint.run)
199+
});
193200

194201
run_level == Some(current_run)
195202
}
@@ -330,17 +337,19 @@ impl WorkspaceWorker {
330337
let server_linter = server_linter_guard.as_ref()?;
331338
server_linter.get_cached_files_of_diagnostics()
332339
};
333-
let options = self.options.lock().await;
334-
let format_options = options.as_ref().map(|o| o.format.clone()).unwrap_or_default();
335-
let lint_options = options.as_ref().map(|o| o.lint.clone()).unwrap_or_default();
340+
let options = {
341+
let options = self.options.lock().await;
342+
serde_json::from_value::<Options>(options.clone().unwrap_or_default())
343+
.unwrap_or_default()
344+
};
336345

337-
if format_options.experimental {
346+
if options.format.experimental {
338347
tokio::join!(
339-
self.refresh_server_formatter(&format_options),
340-
self.refresh_server_linter(&lint_options)
348+
self.refresh_server_formatter(&options.format),
349+
self.refresh_server_linter(&options.lint)
341350
);
342351
} else {
343-
self.refresh_server_linter(&lint_options).await;
352+
self.refresh_server_linter(&options.lint).await;
344353
}
345354

346355
Some(self.revalidate_diagnostics(files).await)
@@ -352,7 +361,7 @@ impl WorkspaceWorker {
352361
/// Panics if the root URI cannot be converted to a file path.
353362
pub async fn did_change_configuration(
354363
&self,
355-
changed_options: &serde_json::Value,
364+
changed_options_json: &serde_json::Value,
356365
) -> (
357366
// Diagnostic reports that need to be revalidated
358367
Option<Vec<(String, Vec<Diagnostic>)>>,
@@ -364,13 +373,13 @@ impl WorkspaceWorker {
364373
bool,
365374
) {
366375
let changed_options: Options =
367-
serde_json::from_value(changed_options.clone()).unwrap_or_default();
376+
serde_json::from_value(changed_options_json.clone()).unwrap_or_default();
368377
// Scope the first lock so it is dropped before the second lock
369378
let current_option = {
370379
let options_guard = self.options.lock().await;
371-
options_guard.clone()
372-
}
373-
.unwrap_or_default();
380+
let current_value = options_guard.clone().unwrap_or_default();
381+
serde_json::from_value::<Options>(current_value).unwrap_or_default()
382+
};
374383

375384
debug!(
376385
"
@@ -382,7 +391,7 @@ impl WorkspaceWorker {
382391

383392
{
384393
let mut options_guard = self.options.lock().await;
385-
*options_guard = Some(changed_options.clone());
394+
*options_guard = Some(changed_options_json.clone());
386395
}
387396

388397
let mut formatting = false;

0 commit comments

Comments
 (0)