lsp_ty/
lib.rs

1mod part1;
2mod part2;
3mod part3;
4mod patch;
5
6use std::fmt::Debug;
7
8pub use part1::*;
9pub use part2::*;
10pub use part3::*;
11pub use patch::*;
12
13/// current lsp version
14pub const VERSION: &str = "3.16";
15
16macro_rules! serde_empty {
17    ($type:ty) => {
18        impl<'de> serde::Deserialize<'de> for $type {
19            fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
20            where
21                D: serde::Deserializer<'de>,
22            {
23                Ok(Self::default())
24            }
25        }
26
27        impl serde::Serialize for $type {
28            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
29            where
30                S: serde::Serializer,
31            {
32                serializer.serialize_none()
33            }
34        }
35    };
36}
37
38serde_empty!(ExitParams);
39serde_empty!(InitializedParams);
40serde_empty!(SemanticTokensRefreshParams);
41serde_empty!(ShutdownParams);
42serde_empty!(WorkspaceFolderParams);
43serde_empty!(Empty);
44
45pub trait FromReq: Sized {
46    const METHOD: &'static str;
47    type Ret;
48
49    /// perform message cast from raw request message
50    /// if method do not match, return `OneOf::Other(request)`
51    fn from_req(req: RequestMessage) -> OneOf<(ReqId, Self), RequestMessage>;
52
53    /// helper function to test method match or not
54    fn can_cast(req: &RequestMessage) -> bool {
55        Self::METHOD == req.method
56    }
57}
58
59#[macro_export]
60macro_rules! impl_req {
61    ($type:ty, $method:literal, $ret:path) => {
62        impl FromReq for $type {
63            const METHOD: &'static str = $method;
64            type Ret = $ret;
65
66            fn from_req(req: RequestMessage) -> OneOf<(ReqId, Self), RequestMessage> {
67                if <Self as FromReq>::can_cast(&req) {
68                    let RequestMessage { id, params, .. } = req;
69                    let params: Self =
70                        serde_json::from_value(params.unwrap_or_else(|| serde_json::Value::Null))
71                            .unwrap();
72                    OneOf::This((id, params))
73                } else {
74                    OneOf::Other(req)
75                }
76            }
77        }
78
79        impl $type {
80            /// helper function for user do not need to remember
81            /// result type of a request
82            pub fn ret(result: $ret) -> $ret {
83                result
84            }
85        }
86    };
87    ($type:ty, $method:literal) => {
88        impl_req!($type, $method, serde_json::Value);
89    };
90}
91
92impl_req!(InitializeParams, "initialize", InitializeResult);
93impl_req!(
94    ShowMessageRequestParams,
95    "window/showMessageRequest",
96    Option<MessageActionItem>
97);
98impl_req!(
99    ShowDocumentParams,
100    "window/showDocument",
101    ShowDocumentResult
102);
103impl_req!(RegistrationParams, "client/registerCapability", Empty);
104impl_req!(UnregistrationParams, "client/unregisterCapability", Empty);
105impl_req!(
106    ConfigurationParams,
107    "workspace/configuration",
108    Vec<serde_json::Value>
109);
110impl_req!(
111    WorkspaceSymbolParams,
112    "workspace/symbol",
113    Vec<SymbolInformation>
114);
115impl_req!(ExecuteCommandParams, "workspace/executeCommand");
116impl_req!(
117    ApplyWorkspaceEditParams,
118    "workspace/applyEdit",
119    ApplyWorkspaceEditResponse
120);
121impl_req!(
122    CreateFilesParams,
123    "workspace/willCreateFiles",
124    Option<WorkspaceEdit>
125);
126impl_req!(
127    RenameFilesParams,
128    "workspace/willRenameFiles",
129    Option<WorkspaceEdit>
130);
131impl_req!(
132    DeleteFilesParams,
133    "workspace/willDeleteFiles",
134    Option<WorkspaceEdit>
135);
136impl_req!(
137    WillSaveTextDocumentParams,
138    "textDocument/willSaveWaitUntil",
139    Vec<TextEdit>
140);
141impl_req!(
142    CompletionParams,
143    "textDocument/completion",
144    OneOf<Vec<CompletionItem>, CompletionList>
145);
146impl_req!(CompletionItem, "completionItem/resolve", CompletionItem);
147impl_req!(HoverParams, "textDocument/hover", Option<Hover>);
148impl_req!(
149    SignatureHelpParams,
150    "textDocument/signatureHelp",
151    Option<SignatureHelp>
152);
153impl_req!(
154    DeclarationParams,
155    "textDocument/declaration",
156    OneOf<Vec<Location>, Vec<LocationLink>>
157);
158impl_req!(
159    DefinitionParams,
160    "textDocument/definition",
161    OneOf<Vec<Location>, Vec<LocationLink>>
162);
163impl_req!(
164    TypeDefinitionParams,
165    "textDocument/typeDefinition",
166    OneOf<Vec<Location>, Vec<LocationLink>>
167);
168impl_req!(
169    ImplementationParams,
170    "textDocument/implementation",
171    OneOf<Vec<Location>, Vec<LocationLink>>
172);
173impl_req!(ReferenceParams, "textDocument/references", Vec<Location>);
174impl_req!(
175    DocumentHighlightParams,
176    "textDocument/documentHighlight",
177    Vec<DocumentHighlight>
178);
179impl_req!(
180    DocumentSymbolParams,
181    "textDocument/documentSymbol",
182    OneOf<Vec<DocumentSymbol>, Vec<SymbolInformation>>
183);
184impl_req!(
185    CodeActionParams,
186    "textDocument/codeAction",
187    Vec<OneOf<Command, CodeAction>>
188);
189impl_req!(CodeAction, "codeAction/resolve", CodeAction);
190impl_req!(CodeLensParams, "textDocument/codeLens", Vec<CodeLens>);
191impl_req!(CodeLens, "codeLens/resolve", CodeLens);
192impl_req!(
193    DocumentLinkParams,
194    "textDocument/documentLink",
195    Vec<DocumentLink>
196);
197impl_req!(DocumentLink, "documentLink/resolve", DocumentLink);
198impl_req!(
199    DocumentFormattingParams,
200    "textDocument/formatting",
201    Vec<TextEdit>
202);
203impl_req!(
204    DocumentRangeFormattingParams,
205    "DocumentRangeFormattingParams",
206    Vec<TextEdit>
207);
208impl_req!(
209    DocumentOnTypeFormattingParams,
210    "textDocument/onTypeFormatting",
211    Vec<TextEdit>
212);
213impl_req!(RenameParams, "textDocument/rename", Option<WorkspaceEdit>);
214impl_req!(
215    PrepareRenameParams,
216    "textDocument/prepareRename",
217    Option<OneOf3<Range, PrepareRenameResult1, PrepareRenameResult2>>
218);
219impl_req!(
220    FoldingRangeParams,
221    "textDocument/foldingRange",
222    Vec<FoldingRange>
223);
224impl_req!(ShutdownParams, "shutdown", Empty);
225impl_req!(
226    WorkDoneProgressCreateParams,
227    "window/workDoneProgress/create",
228    Empty
229);
230impl_req!(
231    CallHierarchyPrepareParams,
232    "textDocument/prepareCallHierarchy",
233    Vec<CallHierarchyItem>
234);
235impl_req!(
236    CallHierarchyIncomingCallsParams,
237    "callHierarchy/incomingCalls",
238    Vec<CallHierarchyIncomingCall>
239);
240impl_req!(
241    CallHierarchyOutgoingCallsParams,
242    "callHierarchy/outgoingCalls",
243    Vec<CallHierarchyOutgoingCall>
244);
245impl_req!(
246    SelectionRangeParams,
247    "textDocument/selectionRange",
248    Vec<SelectionRange>
249);
250impl_req!(
251    WorkspaceFolderParams,
252    "workspace/workspaceFolders",
253    Vec<WorkspaceFolder>
254);
255impl_req!(
256    DocumentColorParams,
257    "textDocument/documentColor",
258    Vec<ColorInformation>
259);
260impl_req!(
261    ColorPresentationParams,
262    "textDocument/colorPresentation",
263    Vec<ColorPresentation>
264);
265impl_req!(
266    SemanticTokensParams,
267    "textDocument/semanticTokens/full",
268    Option<SemanticTokens>
269);
270impl_req!(
271    SemanticTokensDeltaParams,
272    "textDocument/semanticTokens/full/delta",
273    Option<OneOf<SemanticTokens, SemanticTokensDelta>>
274);
275impl_req!(
276    SemanticTokensRangeParams,
277    "textDocument/semanticTokens/range",
278    Option<SemanticTokens>
279);
280impl_req!(
281    SemanticTokensRefreshParams,
282    "workspace/semanticTokens/refresh",
283    Empty
284);
285impl_req!(
286    LinkedEditingRangeParams,
287    "textDocument/linkedEditingRange",
288    Option<LinkedEditingRanges>
289);
290impl_req!(MonikerParams, "textDocument/moniker", Vec<Moniker>);
291
292pub trait FromNotice: Sized + serde::Serialize {
293    const METHOD: &'static str;
294
295    /// perform message cast
296    /// if method do not match, return `OneOf::Other(request)`
297    fn from_notice(notice: NotificationMessage) -> OneOf<Self, NotificationMessage>;
298
299    /// helper method for specify notification down cast to generic Notification
300    /// message
301    fn into_notice(self) -> NotificationMessage {
302        NotificationMessage {
303            jsonrpc: "2.0".to_string(),
304            method: <Self as FromNotice>::METHOD.to_string(),
305            params: Some(serde_json::to_value(self).unwrap()),
306        }
307    }
308
309    /// test method match or not
310    fn can_cast(notice: &NotificationMessage) -> bool {
311        Self::METHOD == notice.method
312    }
313}
314
315#[macro_export]
316macro_rules! impl_notice {
317    ($type:ty, $method:literal) => {
318        impl FromNotice for $type {
319            const METHOD: &'static str = $method;
320
321            fn from_notice(notice: NotificationMessage) -> OneOf<Self, NotificationMessage> {
322                if <Self as FromNotice>::can_cast(&notice) {
323                    let NotificationMessage { params, .. } = notice;
324                    let params =
325                        serde_json::from_value(params.unwrap_or_else(|| serde_json::Value::Null))
326                            .unwrap();
327                    OneOf::This(params)
328                } else {
329                    OneOf::Other(notice)
330                }
331            }
332        }
333    };
334}
335
336impl_notice!(CancelParams, "$/cancelRequest");
337impl_notice!(ProgressParams, "$/progress");
338impl_notice!(InitializedParams, "initialized");
339impl_notice!(ExitParams, "exit");
340impl_notice!(LogTraceParams, "$/logTrace");
341impl_notice!(SetTraceParams, "$/setTrace");
342impl_notice!(ShowMessageParams, "window/showMessage");
343impl_notice!(LogMessageParams, "window/logMessage");
344impl_notice!(
345    WorkDoneProgressCancelParams,
346    "window/workDoneProgress/cancel"
347);
348impl_notice!(
349    DidChangeWorkspaceFoldersParams,
350    "workspace/didChangeWorkspaceFolders"
351);
352impl_notice!(
353    DidChangeConfigurationParams,
354    "workspace/didChangeConfiguration"
355);
356impl_notice!(
357    DidChangeWatchedFilesParams,
358    "workspace/didChangeWatchedFiles"
359);
360impl_notice!(CreateFilesParams, "workspace/didCreateFiles");
361impl_notice!(DeleteFilesParams, "workspace/didDeleteFiles");
362impl_notice!(DidOpenTextDocumentParams, "textDocument/didOpen");
363impl_notice!(DidChangeTextDocumentParams, "textDocument/didChange");
364impl_notice!(WillSaveTextDocumentParams, "textDocument/willSave");
365impl_notice!(DidSaveTextDocumentParams, "textDocument/didSave");
366impl_notice!(DidCloseTextDocumentParams, "textDocument/didClose");
367impl_notice!(PublishDiagnosticsParams, "textDocument/publishDiagnostics");