Skip to content

Commit e2b6233

Browse files
authored
refactor(language_server): add capabilities struct (#7906)
vscode test from local, intellij test from #7445 (comment)
1 parent 0867b40 commit e2b6233

File tree

2 files changed

+140
-45
lines changed

2 files changed

+140
-45
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use tower_lsp::lsp_types::{
2+
ClientCapabilities, CodeActionKind, CodeActionOptions, CodeActionProviderCapability, OneOf,
3+
ServerCapabilities, TextDocumentSyncCapability, TextDocumentSyncKind, WorkDoneProgressOptions,
4+
WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities,
5+
};
6+
7+
pub const CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC: CodeActionKind =
8+
CodeActionKind::new("source.fixAll.oxc");
9+
10+
pub struct Capabilities {
11+
pub code_action_provider: bool,
12+
}
13+
14+
impl From<ClientCapabilities> for Capabilities {
15+
fn from(value: ClientCapabilities) -> Self {
16+
// check if the client support some code action literal support
17+
let code_action_provider = value.text_document.is_some_and(|capability| {
18+
capability.code_action.is_some_and(|code_action| {
19+
code_action.code_action_literal_support.is_some_and(|literal_support| {
20+
!literal_support.code_action_kind.value_set.is_empty()
21+
})
22+
})
23+
});
24+
25+
Self { code_action_provider }
26+
}
27+
}
28+
29+
impl From<Capabilities> for ServerCapabilities {
30+
fn from(value: Capabilities) -> Self {
31+
Self {
32+
text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL)),
33+
workspace: Some(WorkspaceServerCapabilities {
34+
workspace_folders: Some(WorkspaceFoldersServerCapabilities {
35+
supported: Some(true),
36+
change_notifications: Some(OneOf::Left(true)),
37+
}),
38+
file_operations: None,
39+
}),
40+
code_action_provider: if value.code_action_provider {
41+
Some(CodeActionProviderCapability::Options(CodeActionOptions {
42+
code_action_kinds: Some(vec![
43+
CodeActionKind::QUICKFIX,
44+
CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC,
45+
]),
46+
work_done_progress_options: WorkDoneProgressOptions {
47+
work_done_progress: None,
48+
},
49+
resolve_provider: None,
50+
}))
51+
} else {
52+
None
53+
},
54+
..ServerCapabilities::default()
55+
}
56+
}
57+
}
58+
59+
#[cfg(test)]
60+
mod test {
61+
use tower_lsp::lsp_types::{
62+
ClientCapabilities, CodeActionClientCapabilities, CodeActionKindLiteralSupport,
63+
CodeActionLiteralSupport, TextDocumentClientCapabilities,
64+
};
65+
66+
use super::Capabilities;
67+
68+
#[test]
69+
fn test_code_action_provider_vscode() {
70+
let client_capabilities = ClientCapabilities {
71+
text_document: Some(TextDocumentClientCapabilities {
72+
code_action: Some(CodeActionClientCapabilities {
73+
code_action_literal_support: Some(CodeActionLiteralSupport {
74+
code_action_kind: CodeActionKindLiteralSupport {
75+
// this is from build (see help, about):
76+
// Version: 1.95.3 (user setup)
77+
// Commit: f1a4fb101478ce6ec82fe9627c43efbf9e98c813
78+
value_set: vec![
79+
#[allow(clippy::manual_string_new)]
80+
"".into(),
81+
"quickfix".into(),
82+
"refactor".into(),
83+
"refactor.extract".into(),
84+
"refactor.inline".into(),
85+
"refactor.rewrite".into(),
86+
"source".into(),
87+
"source.organizeImports".into(),
88+
],
89+
},
90+
}),
91+
..CodeActionClientCapabilities::default()
92+
}),
93+
..TextDocumentClientCapabilities::default()
94+
}),
95+
..ClientCapabilities::default()
96+
};
97+
98+
let capabilities = Capabilities::from(client_capabilities);
99+
100+
assert!(capabilities.code_action_provider);
101+
}
102+
103+
#[test]
104+
fn test_code_action_provider_intellij() {
105+
let client_capabilities = ClientCapabilities {
106+
text_document: Some(TextDocumentClientCapabilities {
107+
code_action: Some(CodeActionClientCapabilities {
108+
code_action_literal_support: Some(CodeActionLiteralSupport {
109+
code_action_kind: CodeActionKindLiteralSupport {
110+
// this is from build (see help, about):
111+
// Build #IU-243.22562.145, built on December 8, 2024
112+
value_set: vec![
113+
"quickfix".into(),
114+
#[allow(clippy::manual_string_new)]
115+
"".into(),
116+
"source".into(),
117+
"refactor".into(),
118+
],
119+
},
120+
}),
121+
..CodeActionClientCapabilities::default()
122+
}),
123+
..TextDocumentClientCapabilities::default()
124+
}),
125+
..ClientCapabilities::default()
126+
};
127+
128+
let capabilities = Capabilities::from(client_capabilities);
129+
130+
assert!(capabilities.code_action_provider);
131+
}
132+
}

crates/oxc_language_server/src/main.rs

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,21 @@ use tokio::sync::{Mutex, OnceCell, RwLock, SetError};
1111
use tower_lsp::{
1212
jsonrpc::{Error, ErrorCode, Result},
1313
lsp_types::{
14-
CodeAction, CodeActionKind, CodeActionOptions, CodeActionOrCommand, CodeActionParams,
15-
CodeActionProviderCapability, CodeActionResponse, ConfigurationItem, Diagnostic,
16-
DidChangeConfigurationParams, DidChangeTextDocumentParams, DidChangeWatchedFilesParams,
17-
DidCloseTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams,
18-
InitializeParams, InitializeResult, InitializedParams, NumberOrString, OneOf, Position,
19-
Range, ServerCapabilities, ServerInfo, TextDocumentSyncCapability, TextDocumentSyncKind,
20-
TextEdit, Url, WorkDoneProgressOptions, WorkspaceEdit, WorkspaceFoldersServerCapabilities,
21-
WorkspaceServerCapabilities,
14+
CodeAction, CodeActionKind, CodeActionOrCommand, CodeActionParams, CodeActionResponse,
15+
ConfigurationItem, Diagnostic, DidChangeConfigurationParams, DidChangeTextDocumentParams,
16+
DidChangeWatchedFilesParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams,
17+
DidSaveTextDocumentParams, InitializeParams, InitializeResult, InitializedParams,
18+
NumberOrString, Position, Range, ServerInfo, TextEdit, Url, WorkspaceEdit,
2219
},
2320
Client, LanguageServer, LspService, Server,
2421
};
2522

2623
use oxc_linter::{FixKind, LinterBuilder, Oxlintrc};
2724

25+
use crate::capabilities::{Capabilities, CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC};
2826
use crate::linter::{DiagnosticReport, ServerLinter};
2927

28+
mod capabilities;
3029
mod linter;
3130

3231
type FxDashMap<K, V> = DashMap<K, V, FxBuildHasher>;
@@ -88,9 +87,6 @@ enum SyntheticRunLevel {
8887
OnType,
8988
}
9089

91-
const CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC: CodeActionKind =
92-
CodeActionKind::new("source.fixAll.oxc");
93-
9490
#[tower_lsp::async_trait]
9591
impl LanguageServer for Backend {
9692
async fn initialize(&self, params: InitializeParams) -> Result<InitializeResult> {
@@ -106,45 +102,12 @@ impl LanguageServer for Backend {
106102
*self.options.lock().await = value;
107103
}
108104

109-
// check if the client support some code action literal support
110-
let code_action_provider = if params.capabilities.text_document.is_some_and(|capability| {
111-
capability.code_action.is_some_and(|code_action| {
112-
code_action.code_action_literal_support.is_some_and(|literal_support| {
113-
!literal_support.code_action_kind.value_set.is_empty()
114-
})
115-
})
116-
}) {
117-
Some(CodeActionProviderCapability::Options(CodeActionOptions {
118-
code_action_kinds: Some(vec![
119-
CodeActionKind::QUICKFIX,
120-
CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC,
121-
]),
122-
work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
123-
resolve_provider: None,
124-
}))
125-
} else {
126-
None
127-
};
128-
129105
let oxlintrc = self.init_linter_config().await;
130106
self.init_ignore_glob(oxlintrc).await;
131107
Ok(InitializeResult {
132108
server_info: Some(ServerInfo { name: "oxc".into(), version: None }),
133109
offset_encoding: None,
134-
capabilities: ServerCapabilities {
135-
text_document_sync: Some(TextDocumentSyncCapability::Kind(
136-
TextDocumentSyncKind::FULL,
137-
)),
138-
workspace: Some(WorkspaceServerCapabilities {
139-
workspace_folders: Some(WorkspaceFoldersServerCapabilities {
140-
supported: Some(true),
141-
change_notifications: Some(OneOf::Left(true)),
142-
}),
143-
file_operations: None,
144-
}),
145-
code_action_provider,
146-
..ServerCapabilities::default()
147-
},
110+
capabilities: Capabilities::from(params.capabilities).into(),
148111
})
149112
}
150113

0 commit comments

Comments
 (0)