├── rustfmt.toml
├── .gitignore
├── tests
└── dummy.rs
├── .travis.yml
├── .project
├── README.md
├── src
├── lib.rs
├── lsp_transport.rs
├── server_tests.rs
└── lsp.rs
├── Cargo.toml
└── LICENSE
/rustfmt.toml:
--------------------------------------------------------------------------------
1 | max_width=120
2 | hard_tabs=true
3 | normalise_comments=false
4 | wrap_comments=false
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | /Cargo.lock
3 | /subcrates/melnorme*/Cargo.lock
4 | # Ignore Eclipse settings:
5 | .settings/
--------------------------------------------------------------------------------
/tests/dummy.rs:
--------------------------------------------------------------------------------
1 | // Blank file, workaround to make `cargo test` build all targets, see:
2 | // https://github.com/rust-lang/cargo/issues/2495#issuecomment-235114484
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: rust
2 |
3 | rust:
4 | # - 1.10.0
5 | # - stable
6 | # - beta
7 | - nightly
8 |
9 | matrix:
10 | allow_failures:
11 | - rust: nightly
12 |
13 | script:
14 | - cargo build --verbose
15 | - cargo test --verbose
16 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | RustLSP
4 |
5 |
6 |
7 |
8 |
9 | com.github.rustdt.ide.core.Builder
10 | clean,full,incremental,
11 |
12 |
13 |
14 |
15 |
16 | com.github.rustdt.ide.core.nature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/RustDT/RustLSP)
2 |
3 | # RustLSP
4 | A library for working with the Language Server Protocol, as either client or server.
5 | (LSP protocol only, not tied to any particular language engine)
6 |
7 | ## Examples:
8 |
9 | See full server/client example here:
10 | [src/server_tests.rs](src/server_tests.rs)
11 |
12 | ### Projects using RustLSP:
13 | * [MockLS](https://github.com/RustDT/MockLS)
14 | * [RLS](https://github.com/jonathandturner/rls/pull/96) (in PR only)
15 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 |
2 | /*!
3 |
4 | ### RustLSP
5 |
6 | # Examples:
7 |
8 | See full server/client example here:
9 | https://github.com/RustDT/RustLSP/blob/master/src/server_tests.rs
10 |
11 | */
12 |
13 |
14 | #![allow(non_snake_case)]
15 | #![allow(non_camel_case_types)]
16 | #![allow(non_upper_case_globals)]
17 |
18 | extern crate serde_json;
19 | extern crate serde;
20 |
21 | pub extern crate rustdt_util as util;
22 | pub extern crate jsonrpc;
23 | pub extern crate languageserver_types as ls_types;
24 |
25 | #[macro_use] extern crate log;
26 |
27 | pub mod lsp_transport;
28 | pub mod lsp;
29 |
30 | #[cfg(test)]
31 | mod server_tests;
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "rust_lsp"
3 | version = "0.6.0"
4 | authors = ["Bruno Medeiros "]
5 |
6 | description = "A library for working with the Language Server Protocol, as either client or server."
7 | repository = "https://github.com/RustDT/rustlsp"
8 | documentation = "https://docs.rs/rustlsp"
9 | license = "Apache-2.0"
10 | keywords = ["rustlsp", "lsp"]
11 |
12 |
13 | [build-dependencies]
14 | serde_codegen = { version = "0.8", optional = true }
15 |
16 | [dependencies]
17 | rustdt_util = "0.2.3"
18 | rustdt-json_rpc = "0.3.0"
19 | log = "0.3.6"
20 | serde = "0.8"
21 | serde_json = "0.8"
22 | languageserver-types = { version = "0.6.0" }
23 |
24 |
25 | [lib]
26 | name = "rust_lsp"
27 | path = "src/lib.rs"
28 |
--------------------------------------------------------------------------------
/src/lsp_transport.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Bruno Medeiros
2 | //
3 | // Licensed under the Apache License, Version 2.0
4 | // .
5 | // This file may not be copied, modified, or distributed
6 | // except according to those terms.
7 |
8 |
9 | use std::io::{self, Read};
10 |
11 | use util::core::*;
12 |
13 | use jsonrpc::service_util::MessageReader;
14 | use jsonrpc::service_util::MessageWriter;
15 |
16 | /* ----------------- ----------------- */
17 |
18 | pub struct LSPMessageReader(pub T);
19 |
20 | impl MessageReader for LSPMessageReader {
21 | fn read_next(&mut self) -> GResult {
22 | parse_transport_message(&mut self.0)
23 | }
24 | }
25 |
26 | pub struct LSPMessageWriter(pub T);
27 |
28 | impl MessageWriter for LSPMessageWriter {
29 | fn write_message(&mut self, msg: &str) -> Result<(), GError> {
30 | write_transport_message(msg, &mut self.0)
31 | }
32 | }
33 |
34 | /* ----------------- Parse content-length ----------------- */
35 |
36 | const CONTENT_LENGTH: &'static str = "Content-Length:";
37 |
38 | pub fn parse_transport_message(reader: &mut R) -> GResult
39 | {
40 |
41 | let mut content_length : u32 = 0;
42 |
43 | loop {
44 | let mut line = String::new();
45 |
46 | try!(reader.read_line(&mut line));
47 |
48 | if line.starts_with(CONTENT_LENGTH) {
49 | let len_str : &str = &line[CONTENT_LENGTH.len()..];
50 | let int_result = len_str.trim().parse::();
51 |
52 | content_length = try!(int_result);
53 |
54 | } else if line.eq("\r\n") {
55 | break;
56 | } else if line.is_empty() {
57 | return Err("End of stream reached.".into());
58 | }
59 | }
60 | if content_length == 0 {
61 | return Err((String::from(CONTENT_LENGTH) + " not defined or invalid.").into());
62 | }
63 |
64 | let mut message_reader = reader.take(content_length as u64);
65 | let mut message = String::new();
66 | try!(message_reader.read_to_string(&mut message));
67 | return Ok(message);
68 | }
69 |
70 |
71 | #[test]
72 | fn parse_transport_message__test() {
73 | use std::io::BufReader;
74 |
75 | let string = "Content-Length: 10 \r\n\r\n1234567890abcdef";
76 | assert_eq!(parse_transport_message(&mut BufReader::new(string.as_bytes())).unwrap(), "1234567890");
77 |
78 | // Allow other header fields
79 | let string = "Content-Length: 13 \r\nContent-Blah\r\n\r\n1234\n567\r\n890abcdef";
80 | assert_eq!(parse_transport_message(&mut BufReader::new(string.as_bytes())).unwrap(), "1234\n567\r\n890");
81 |
82 | // Test no-content
83 | let string = "\r\n\r\n1234567890abcdef";
84 | let err : GError = parse_transport_message(&mut BufReader::new(string.as_bytes())).unwrap_err();
85 | assert_eq!(&err.to_string(), "Content-Length: not defined or invalid.");
86 |
87 | // Test EOS
88 | let string = "";
89 | let err : GError = parse_transport_message(&mut BufReader::new(string.as_bytes())).unwrap_err();
90 | assert_eq!(&err.to_string(), "End of stream reached.");
91 |
92 | }
93 |
94 | pub fn write_transport_message(message: & str, out: &mut WRITE) -> GResult<()>
95 | {
96 | // let out : &mut io::Write = out;
97 | try!(out.write_all(CONTENT_LENGTH.as_bytes()));
98 | try!(out.write(&[' ' as u8]));
99 | let contents = message.as_bytes();
100 | try!(out.write_all(contents.len().to_string().as_bytes()));
101 | try!(out.write_all("\r\n\r\n".as_bytes()));
102 | try!(out.write_all(message.as_bytes()));
103 | try!(out.flush());
104 | Ok(())
105 | }
106 |
107 |
108 | #[test]
109 | fn write_transport_message__test() {
110 | use util::tests::*;
111 |
112 | let mut out : Vec = vec!['x' as u8];
113 | write_transport_message(&"1234\n67", &mut out).unwrap();
114 |
115 | assert_equal(String::from_utf8(out).unwrap(), "xContent-Length: 7\r\n\r\n1234\n67".to_string());
116 | }
--------------------------------------------------------------------------------
/src/server_tests.rs:
--------------------------------------------------------------------------------
1 | /* ----------------- Tests ----------------- */
2 |
3 |
4 | use lsp::*;
5 | use jsonrpc::method_types::MethodError;
6 | use jsonrpc::*;
7 | use ls_types::*;
8 |
9 | use jsonrpc::json_util::JsonObject;
10 | use serde_json::Value;
11 |
12 | use std::io;
13 | use std::thread;
14 | use std::net::TcpListener;
15 | use std::net::TcpStream;
16 |
17 |
18 | #[test]
19 | pub fn test_run_lsp_server() {
20 |
21 | let listener = TcpListener::bind(("127.0.0.1", 0)).unwrap();
22 | let local_addr = listener.local_addr().unwrap();
23 |
24 | let server_listener = thread::spawn(|| {
25 | tcp_server(listener)
26 | });
27 |
28 | let stream = TcpStream::connect(local_addr).unwrap();
29 | let out_stream = stream.try_clone().expect("Failed to clone stream");
30 | let mut endpoint = LSPEndpoint::create_lsp_output_with_output_stream(|| { out_stream });
31 |
32 | let ls_client = TestsLanguageClient { counter: 0, endpoint : endpoint.clone() };
33 |
34 | let client_handler = thread::spawn(|| {
35 | let mut input = io::BufReader::new(stream);
36 | let endpoint = ls_client.endpoint.clone();
37 | LSPEndpoint::run_client_from_input(&mut input, endpoint, ls_client);
38 | });
39 |
40 | let init_params = InitializeParams {
41 | process_id: None,
42 | root_path: None,
43 | initialization_options: None,
44 | capabilities: Value::Object(JsonObject::new()),
45 | };
46 |
47 | // Create an rpc handle to the server methods
48 | let mut server_handle = server_rpc_handle(&mut endpoint);
49 |
50 | server_handle.initialize(init_params).unwrap();
51 |
52 | server_handle.shutdown().unwrap();
53 |
54 | server_handle.exit().unwrap();
55 |
56 | client_handler.join().unwrap();
57 | server_listener.join().unwrap();
58 | }
59 |
60 | fn tcp_server(listener: TcpListener) {
61 |
62 | for stream in listener.incoming() {
63 | let stream = stream.expect("Failed to open incoming stream");
64 | let conn_handler = thread::spawn(move|| {
65 | handle_connection(stream)
66 | });
67 |
68 | // Only listen to first connection, so that this example can be run as a test
69 | conn_handler.join().unwrap();
70 | break;
71 | }
72 |
73 | drop(listener);
74 | }
75 |
76 | fn handle_connection(stream: TcpStream) {
77 | let out_stream = stream.try_clone().expect("Failed to clone stream");
78 | let endpoint = LSPEndpoint::create_lsp_output_with_output_stream(|| { out_stream });
79 |
80 | let ls = TestsLanguageServer { counter : 0, endpoint : endpoint.clone() };
81 |
82 | let mut input = io::BufReader::new(stream);
83 | LSPEndpoint::run_server_from_input(&mut input, endpoint, ls);
84 | }
85 |
86 | pub struct TestsLanguageServer {
87 | counter: u32,
88 | endpoint: Endpoint,
89 | }
90 |
91 | impl TestsLanguageServer {
92 |
93 | pub fn error_not_available(data : DATA) -> MethodError {
94 | let msg = "Functionality not implemented.".to_string();
95 | MethodError:: { code : 1, message : msg, data : data }
96 | }
97 |
98 | }
99 |
100 | impl LanguageServerHandling for TestsLanguageServer {
101 |
102 | fn initialize(&mut self, _: InitializeParams, completable: MethodCompletable) {
103 | let capabilities = ServerCapabilities::default();
104 | assert_eq!(self.counter, 0);
105 | self.counter = 1;
106 | completable.complete(Ok(InitializeResult { capabilities : capabilities }))
107 | }
108 | fn shutdown(&mut self, _: (), completable: LSCompletable<()>) {
109 | completable.complete(Ok(()));
110 | }
111 | fn exit(&mut self, _: ()) {
112 | self.endpoint.request_shutdown();
113 | }
114 |
115 | fn workspace_change_configuration(&mut self, _: DidChangeConfigurationParams) {}
116 | fn did_open_text_document(&mut self, _: DidOpenTextDocumentParams) {}
117 | fn did_change_text_document(&mut self, _: DidChangeTextDocumentParams) {}
118 | fn did_close_text_document(&mut self, _: DidCloseTextDocumentParams) {}
119 | fn did_save_text_document(&mut self, _: DidSaveTextDocumentParams) {}
120 | fn did_change_watched_files(&mut self, _: DidChangeWatchedFilesParams) {}
121 |
122 | fn completion(&mut self, _: TextDocumentPositionParams, completable: LSCompletable) {
123 | completable.complete(Err(Self::error_not_available(())));
124 | }
125 | fn resolve_completion_item(&mut self, _: CompletionItem, completable: LSCompletable) {
126 | completable.complete(Err(Self::error_not_available(())));
127 | }
128 | fn hover(&mut self, _: TextDocumentPositionParams, completable: LSCompletable) {
129 | let mut endpoint = self.endpoint.clone();
130 | thread::spawn(move || {
131 | client_rpc_handle(&mut endpoint).telemetry_event(Value::Null)
132 | .unwrap();
133 |
134 | let hover_str = "hover_text".to_string();
135 | let hover = Hover { contents: vec![MarkedString::String(hover_str)], range: None };
136 |
137 | completable.complete(Ok(hover));
138 | });
139 | }
140 | fn signature_help(&mut self, _: TextDocumentPositionParams, completable: LSCompletable) {
141 | completable.complete(Err(Self::error_not_available(())));
142 | }
143 | fn goto_definition(&mut self, _: TextDocumentPositionParams, completable: LSCompletable>) {
144 | completable.complete(Err(Self::error_not_available(())));
145 | }
146 | fn references(&mut self, _: ReferenceParams, completable: LSCompletable>) {
147 | completable.complete(Err(Self::error_not_available(())));
148 | }
149 | fn document_highlight(&mut self, _: TextDocumentPositionParams, completable: LSCompletable>) {
150 | completable.complete(Err(Self::error_not_available(())));
151 | }
152 | fn document_symbols(&mut self, _: DocumentSymbolParams, completable: LSCompletable>) {
153 | completable.complete(Err(Self::error_not_available(())));
154 | }
155 | fn workspace_symbols(&mut self, _: WorkspaceSymbolParams, completable: LSCompletable>) {
156 | completable.complete(Err(Self::error_not_available(())));
157 | }
158 | fn code_action(&mut self, _: CodeActionParams, completable: LSCompletable>) {
159 | completable.complete(Err(Self::error_not_available(())));
160 | }
161 | fn code_lens(&mut self, _: CodeLensParams, completable: LSCompletable>) {
162 | completable.complete(Err(Self::error_not_available(())));
163 | }
164 | fn code_lens_resolve(&mut self, _: CodeLens, completable: LSCompletable) {
165 | completable.complete(Err(Self::error_not_available(())));
166 | }
167 | fn document_link(&mut self, _params: DocumentLinkParams, completable: LSCompletable>) {
168 | completable.complete(Err(Self::error_not_available(())));
169 | }
170 | fn document_link_resolve(&mut self, _params: DocumentLink, completable: LSCompletable) {
171 | completable.complete(Err(Self::error_not_available(())));
172 | }
173 | fn formatting(&mut self, _: DocumentFormattingParams, completable: LSCompletable>) {
174 | completable.complete(Err(Self::error_not_available(())));
175 | }
176 | fn range_formatting(&mut self, _: DocumentRangeFormattingParams, completable: LSCompletable>) {
177 | completable.complete(Err(Self::error_not_available(())));
178 | }
179 | fn on_type_formatting(&mut self, _: DocumentOnTypeFormattingParams, completable: LSCompletable>) {
180 | completable.complete(Err(Self::error_not_available(())));
181 | }
182 | fn rename(&mut self, _: RenameParams, completable: LSCompletable) {
183 | completable.complete(Err(Self::error_not_available(())));
184 | }
185 | }
186 |
187 | /* ----------------- ----------------- */
188 |
189 | pub struct TestsLanguageClient {
190 | counter: u32,
191 | endpoint: Endpoint,
192 | }
193 |
194 | #[allow(unused_variables)]
195 | impl LanguageClientHandling for TestsLanguageClient {
196 |
197 | fn show_message(&mut self, params: ShowMessageParams) {
198 |
199 | }
200 |
201 | fn show_message_request(
202 | &mut self, params: ShowMessageRequestParams, completable: LSCompletable
203 | ) {
204 | unimplemented!();
205 | }
206 |
207 | fn log_message(&mut self, params: LogMessageParams) {
208 |
209 | }
210 |
211 | fn telemetry_event(&mut self, params: Value) {
212 | self.counter += 1;
213 | }
214 |
215 | fn publish_diagnostics(&mut self, params: PublishDiagnosticsParams) {
216 |
217 | }
218 |
219 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/src/lsp.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Bruno Medeiros
2 | //
3 | // Licensed under the Apache License, Version 2.0
4 | // .
5 | // This file may not be copied, modified, or distributed
6 | // except according to those terms.
7 |
8 |
9 | use std::io;
10 |
11 | use util::core::*;
12 |
13 | use jsonrpc::*;
14 | pub use jsonrpc::service_util::MessageReader;
15 | pub use jsonrpc::service_util::MessageWriter;
16 |
17 | use jsonrpc::output_agent::OutputAgent;
18 |
19 | use jsonrpc::method_types::MethodError;
20 | use jsonrpc::jsonrpc_request::RequestParams;
21 |
22 | use lsp_transport::LSPMessageWriter;
23 | use lsp_transport::LSPMessageReader;
24 | use ls_types::*;
25 | use serde_json::Value;
26 |
27 | /* ----------------- ----------------- */
28 |
29 | /// Helper empty type to help create a JSON-RPC endpoint for LSP communication
30 | pub struct LSPEndpoint {
31 |
32 | }
33 |
34 | impl LSPEndpoint {
35 |
36 | /// Create an Endpoint for use in the Language Server Protocol,
37 | /// with given output stream provider.
38 | pub fn create_lsp_output_with_output_stream(output_stream_provider: OUT_PROV)
39 | -> Endpoint
40 | where
41 | OUT : io::Write + 'static,
42 | OUT_PROV : FnOnce() -> OUT + Send + 'static
43 | {
44 | Self::create_lsp_output(|| {
45 | LSPMessageWriter(output_stream_provider())
46 | })
47 | }
48 |
49 | /// Create an Endpoint for use in the Language Server Protocol
50 | /// with given message writer provider.
51 | pub fn create_lsp_output(msg_writer_provider: MW_PROV)
52 | -> Endpoint
53 | where
54 | MW : MessageWriter + 'static,
55 | MW_PROV : FnOnce() -> MW + Send + 'static
56 | {
57 | let output_agent = OutputAgent::start_with_provider(msg_writer_provider);
58 | Endpoint::start_with(output_agent)
59 | }
60 |
61 | /* ----------------- ----------------- */
62 |
63 | pub fn run_server_from_input(
64 | input: &mut io::BufRead, endpoint: Endpoint, lsp_server_handler: SERVER,
65 | )
66 | where
67 | SERVER : LanguageServerHandling + 'static,
68 | {
69 | Self::run_server(&mut LSPMessageReader(input), endpoint, lsp_server_handler)
70 | }
71 |
72 | /// Run the message read loop on the server, for given msg_reader.
73 | /// msg_reader must be a LSPMessageReader or compatible.
74 | pub fn run_server(
75 | mut msg_reader: &mut MR, endpoint: Endpoint, lsp_server_handler: SERVER
76 | )
77 | where
78 | SERVER : LanguageServerHandling + 'static,
79 | MR : MessageReader,
80 | {
81 | Self::run_endpoint_loop(msg_reader, endpoint, new(ServerRequestHandler(lsp_server_handler)))
82 | }
83 |
84 | pub fn run_client_from_input(
85 | input: &mut io::BufRead, endpoint: Endpoint, lsp_client_handler: CLIENT,
86 | )
87 | where
88 | CLIENT : LanguageClientHandling + 'static,
89 | {
90 | let cl_handler = new(ClientRequestHandler(lsp_client_handler));
91 | Self::run_endpoint_loop(&mut LSPMessageReader(input), endpoint, cl_handler)
92 | }
93 |
94 | pub fn run_endpoint_loop(
95 | mut msg_reader: &mut MR, endpoint: Endpoint, request_handler: Box
96 | )
97 | where
98 | MR : MessageReader,
99 | {
100 | info!("Starting LSP Endpoint");
101 |
102 | let endpoint = EndpointHandler::create(endpoint, request_handler);
103 |
104 | let result = endpoint.run_message_read_loop(msg_reader);
105 |
106 | if let Err(error) = result {
107 | error!("Error handling the incoming stream: {}", error);
108 | }
109 | }
110 |
111 | }
112 |
113 | pub type LSResult = Result>;
114 | pub type LSCompletable = MethodCompletable;
115 |
116 | /// Trait for the handling of LSP server requests
117 | pub trait LanguageServerHandling {
118 |
119 | fn initialize(&mut self, params: InitializeParams, completable: MethodCompletable);
120 | fn shutdown(&mut self, params: (), completable: LSCompletable<()>);
121 | fn exit(&mut self, params: ());
122 | fn workspace_change_configuration(&mut self, params: DidChangeConfigurationParams);
123 | fn did_open_text_document(&mut self, params: DidOpenTextDocumentParams);
124 | fn did_change_text_document(&mut self, params: DidChangeTextDocumentParams);
125 | fn did_close_text_document(&mut self, params: DidCloseTextDocumentParams);
126 | fn did_save_text_document(&mut self, params: DidSaveTextDocumentParams);
127 | fn did_change_watched_files(&mut self, params: DidChangeWatchedFilesParams);
128 |
129 | fn completion(&mut self, params: TextDocumentPositionParams, completable: LSCompletable);
130 | fn resolve_completion_item(&mut self, params: CompletionItem, completable: LSCompletable);
131 | fn hover(&mut self, params: TextDocumentPositionParams, completable: LSCompletable);
132 | fn signature_help(&mut self, params: TextDocumentPositionParams, completable: LSCompletable);
133 | fn goto_definition(&mut self, params: TextDocumentPositionParams, completable: LSCompletable>);
134 | fn references(&mut self, params: ReferenceParams, completable: LSCompletable>);
135 | fn document_highlight(&mut self, params: TextDocumentPositionParams, completable: LSCompletable>);
136 | fn document_symbols(&mut self, params: DocumentSymbolParams, completable: LSCompletable>);
137 | fn workspace_symbols(&mut self, params: WorkspaceSymbolParams, completable: LSCompletable>);
138 | fn code_action(&mut self, params: CodeActionParams, completable: LSCompletable>);
139 | fn code_lens(&mut self, params: CodeLensParams, completable: LSCompletable>);
140 | fn code_lens_resolve(&mut self, params: CodeLens, completable: LSCompletable);
141 | fn document_link(&mut self, params: DocumentLinkParams, completable: LSCompletable>);
142 | fn document_link_resolve(&mut self, params: DocumentLink, completable: LSCompletable);
143 | fn formatting(&mut self, params: DocumentFormattingParams, completable: LSCompletable>);
144 | fn range_formatting(&mut self, params: DocumentRangeFormattingParams, completable: LSCompletable>);
145 | fn on_type_formatting(&mut self, params: DocumentOnTypeFormattingParams, completable: LSCompletable>);
146 | fn rename(&mut self, params: RenameParams, completable: LSCompletable);
147 |
148 | #[allow(unused_variables)]
149 | fn handle_other_method(&mut self, method_name: &str, params: RequestParams, completable: ResponseCompletable) {
150 | completable.complete_with_error(jsonrpc_common::error_JSON_RPC_MethodNotFound());
151 | }
152 | }
153 |
154 |
155 | pub struct ServerRequestHandler(pub LS);
156 |
157 | impl RequestHandler for ServerRequestHandler {
158 |
159 | fn handle_request(
160 | &mut self, method_name: &str, params: RequestParams, completable: ResponseCompletable
161 | ) {
162 | match method_name {
163 | REQUEST__Initialize => {
164 | completable.handle_request_with(params,
165 | |params, completable| self.0.initialize(params, completable)
166 | )
167 | }
168 | REQUEST__Shutdown => {
169 | completable.handle_request_with(params,
170 | |params, completable| self.0.shutdown(params, completable)
171 | )
172 | }
173 | NOTIFICATION__Exit => {
174 | completable.handle_notification_with(params,
175 | |params| self.0.exit(params))
176 | }
177 | NOTIFICATION__WorkspaceChangeConfiguration => {
178 | completable.handle_notification_with(params,
179 | |params| self.0.workspace_change_configuration(params)
180 | )
181 | }
182 | NOTIFICATION__DidOpenTextDocument => {
183 | completable.handle_notification_with(params,
184 | |params| self.0.did_open_text_document(params)
185 | )
186 | }
187 | NOTIFICATION__DidChangeTextDocument => {
188 | completable.handle_notification_with(params,
189 | |params| self.0.did_change_text_document(params)
190 | )
191 | }
192 | NOTIFICATION__DidCloseTextDocument => {
193 | completable.handle_notification_with(params,
194 | |params| self.0.did_close_text_document(params)
195 | )
196 | }
197 | NOTIFICATION__DidSaveTextDocument => {
198 | completable.handle_notification_with(params,
199 | |params| self.0.did_save_text_document(params)
200 | )
201 | }
202 | NOTIFICATION__DidChangeWatchedFiles => {
203 | completable.handle_notification_with(params,
204 | |params| self.0.did_change_watched_files(params))
205 | }
206 | REQUEST__Completion => {
207 | completable.handle_request_with(params,
208 | |params, completable| self.0.completion(params, completable)
209 | )
210 | }
211 | REQUEST__ResolveCompletionItem => {
212 | completable.handle_request_with(params,
213 | |params, completable| self.0.resolve_completion_item(params, completable)
214 | )
215 | }
216 | REQUEST__Hover => {
217 | completable.handle_request_with(params,
218 | |params, completable| self.0.hover(params, completable)
219 | )
220 | }
221 | REQUEST__SignatureHelp => {
222 | completable.handle_request_with(params,
223 | |params, completable| self.0.signature_help(params, completable)
224 | )
225 | }
226 | REQUEST__GotoDefinition => {
227 | completable.handle_request_with(params,
228 | |params, completable| self.0.goto_definition(params, completable)
229 | )
230 | }
231 | REQUEST__References => {
232 | completable.handle_request_with(params,
233 | |params, completable| self.0.references(params, completable)
234 | )
235 | }
236 | REQUEST__DocumentHighlight => {
237 | completable.handle_request_with(params,
238 | |params, completable| self.0.document_highlight(params, completable)
239 | )
240 | }
241 | REQUEST__DocumentSymbols => {
242 | completable.handle_request_with(params,
243 | |params, completable| self.0.document_symbols(params, completable)
244 | )
245 | }
246 | REQUEST__WorkspaceSymbols => {
247 | completable.handle_request_with(params,
248 | |params, completable| self.0.workspace_symbols(params, completable)
249 | )
250 | }
251 | REQUEST__CodeAction => {
252 | completable.handle_request_with(params,
253 | |params, completable| self.0.code_action(params, completable)
254 | )
255 | }
256 | REQUEST__CodeLens => {
257 | completable.handle_request_with(params,
258 | |params, completable| self.0.code_lens(params, completable)
259 | )
260 | }
261 | REQUEST__CodeLensResolve => {
262 | completable.handle_request_with(params,
263 | |params, completable| self.0.code_lens_resolve(params, completable)
264 | )
265 | }
266 | REQUEST__DocumentLink => {
267 | completable.handle_request_with(params,
268 | |params, completable| self.0.document_link(params, completable)
269 | )
270 | }
271 | REQUEST__DocumentLinkResolve => {
272 | completable.handle_request_with(params,
273 | |params, completable| self.0.document_link_resolve(params, completable)
274 | )
275 | }
276 | REQUEST__Formatting => {
277 | completable.handle_request_with(params,
278 | |params, completable| self.0.formatting(params, completable)
279 | )
280 | }
281 | REQUEST__RangeFormatting => {
282 | completable.handle_request_with(params,
283 | |params, completable| self.0.range_formatting(params, completable)
284 | )
285 | }
286 | REQUEST__OnTypeFormatting => {
287 | completable.handle_request_with(params,
288 | |params, completable| self.0.on_type_formatting(params, completable)
289 | )
290 | }
291 | REQUEST__Rename => {
292 | completable.handle_request_with(params,
293 | |params, completable| self.0.rename(params, completable)
294 | )
295 | }
296 | _ => {
297 | self.0.handle_other_method(method_name, params, completable);
298 | }
299 | };
300 |
301 | }
302 |
303 | }
304 |
305 |
306 | pub trait LspClientRpc {
307 |
308 | fn show_message(&mut self, params: ShowMessageParams)
309 | -> GResult<()>;
310 |
311 | fn show_message_request(&mut self, params: ShowMessageRequestParams)
312 | -> GResult>;
313 |
314 | fn log_message(&mut self, params: LogMessageParams)
315 | -> GResult<()>;
316 |
317 | fn telemetry_event(&mut self, params: Value)
318 | -> GResult<()>;
319 |
320 | fn publish_diagnostics(&mut self, params: PublishDiagnosticsParams)
321 | -> GResult<()>;
322 |
323 | }
324 |
325 | pub struct LspClientRpc_<'a> {
326 | pub endpoint: &'a mut Endpoint,
327 | }
328 |
329 | pub fn client_rpc_handle(endpoint : &mut Endpoint) -> LspClientRpc_ {
330 | LspClientRpc_ { endpoint: endpoint }
331 | }
332 |
333 | impl<'a> LspClientRpc for LspClientRpc_<'a> {
334 |
335 | fn show_message(&mut self, params: ShowMessageParams)
336 | -> GResult<()>
337 | {
338 | self.endpoint.send_notification(NOTIFICATION__ShowMessage, params)
339 | }
340 |
341 | fn show_message_request(&mut self, params: ShowMessageRequestParams)
342 | -> GResult>
343 | {
344 | self.endpoint.send_request(REQUEST__ShowMessageRequest, params)
345 | }
346 |
347 | fn log_message(&mut self, params: LogMessageParams)
348 | -> GResult<()>
349 | {
350 | self.endpoint.send_notification(NOTIFICATION__LogMessage, params)
351 | }
352 |
353 | fn telemetry_event(&mut self, params: Value)
354 | -> GResult<()>
355 | {
356 | self.endpoint.send_notification(NOTIFICATION__TelemetryEvent, params)
357 | }
358 |
359 | fn publish_diagnostics(&mut self, params: PublishDiagnosticsParams)
360 | -> GResult<()>
361 | {
362 | self.endpoint.send_notification(NOTIFICATION__PublishDiagnostics, params)
363 | }
364 |
365 | }
366 |
367 | /* ----------------- LSP Client: ----------------- */
368 |
369 | pub trait LSPServerRpc {
370 |
371 | fn initialize(&mut self, params: InitializeParams)
372 | -> GResult>;
373 |
374 | fn shutdown(&mut self)
375 | -> GResult>;
376 |
377 | fn exit(&mut self)
378 | -> GResult<()>;
379 |
380 | fn workspace_change_configuration(&mut self, params: DidChangeConfigurationParams)
381 | -> GResult<()>;
382 |
383 | fn did_open_text_document(&mut self, params: DidOpenTextDocumentParams)
384 | -> GResult<()>;
385 |
386 | fn did_change_text_document(&mut self, params: DidChangeTextDocumentParams)
387 | -> GResult<()>;
388 |
389 | fn did_close_text_document(&mut self, params: DidCloseTextDocumentParams)
390 | -> GResult<()>;
391 |
392 | fn did_save_text_document(&mut self, params: DidSaveTextDocumentParams)
393 | -> GResult<()>;
394 |
395 | fn did_change_watched_files(&mut self, params: DidChangeWatchedFilesParams)
396 | -> GResult<()>;
397 |
398 | fn completion(&mut self, params: TextDocumentPositionParams)
399 | -> GResult>;
400 |
401 | fn resolve_completion_item(&mut self, params: CompletionItem)
402 | -> GResult>;
403 |
404 | fn hover(&mut self, params: TextDocumentPositionParams)
405 | -> GResult>;
406 |
407 | fn signature_help(&mut self, params: TextDocumentPositionParams)
408 | -> GResult>;
409 |
410 | fn goto_definition(&mut self, params: TextDocumentPositionParams)
411 | -> GResult, ()>>;
412 |
413 | fn references(&mut self, params: ReferenceParams)
414 | -> GResult, ()>>;
415 |
416 | fn document_highlight(&mut self, params: TextDocumentPositionParams)
417 | -> GResult, ()>>;
418 |
419 | fn document_symbols(&mut self, params: DocumentSymbolParams)
420 | -> GResult, ()>>;
421 |
422 | fn workspace_symbols(&mut self, params: WorkspaceSymbolParams)
423 | -> GResult, ()>>;
424 |
425 | fn code_action(&mut self, params: CodeActionParams)
426 | -> GResult, ()>>;
427 |
428 | fn code_lens(&mut self, params: CodeLensParams)
429 | -> GResult, ()>>;
430 |
431 | fn code_lens_resolve(&mut self, params: CodeLens)
432 | -> GResult>;
433 |
434 | fn formatting(&mut self, params: DocumentFormattingParams)
435 | -> GResult, ()>>;
436 |
437 | fn range_formatting(&mut self, params: DocumentRangeFormattingParams)
438 | -> GResult, ()>>;
439 |
440 | fn on_type_formatting(&mut self, params: DocumentOnTypeFormattingParams)
441 | -> GResult, ()>>;
442 |
443 | fn rename(&mut self, params: RenameParams)
444 | -> GResult>;
445 |
446 | }
447 |
448 |
449 | pub struct LspServerRpc_<'a> {
450 | pub endpoint: &'a mut Endpoint,
451 | }
452 |
453 | pub fn server_rpc_handle(endpoint : &mut Endpoint) -> LspServerRpc_ {
454 | LspServerRpc_ { endpoint: endpoint }
455 | }
456 |
457 | impl<'a> LSPServerRpc for LspServerRpc_<'a> {
458 |
459 | fn initialize(&mut self, params: InitializeParams)
460 | -> GResult>
461 | {
462 | self.endpoint.send_request(REQUEST__Initialize, params)
463 | }
464 |
465 | fn shutdown(&mut self)
466 | -> GResult>
467 | {
468 | self.endpoint.send_request(REQUEST__Shutdown, ())
469 | }
470 |
471 | fn exit(&mut self)
472 | -> GResult<()>
473 | {
474 | self.endpoint.send_notification(NOTIFICATION__Exit, ())
475 | }
476 |
477 | fn workspace_change_configuration(&mut self, params: DidChangeConfigurationParams)
478 | -> GResult<()>
479 | {
480 | self.endpoint.send_notification(NOTIFICATION__WorkspaceChangeConfiguration, params)
481 | }
482 |
483 | fn did_open_text_document(&mut self, params: DidOpenTextDocumentParams)
484 | -> GResult<()>
485 | {
486 | self.endpoint.send_notification(NOTIFICATION__DidOpenTextDocument, params)
487 | }
488 |
489 | fn did_change_text_document(&mut self, params: DidChangeTextDocumentParams)
490 | -> GResult<()>
491 | {
492 | self.endpoint.send_notification(NOTIFICATION__DidChangeTextDocument, params)
493 | }
494 |
495 | fn did_close_text_document(&mut self, params: DidCloseTextDocumentParams)
496 | -> GResult<()>
497 | {
498 | self.endpoint.send_notification(NOTIFICATION__DidCloseTextDocument, params)
499 | }
500 |
501 | fn did_save_text_document(&mut self, params: DidSaveTextDocumentParams)
502 | -> GResult<()>
503 | {
504 | self.endpoint.send_notification(NOTIFICATION__DidSaveTextDocument, params)
505 | }
506 |
507 | fn did_change_watched_files(&mut self, params: DidChangeWatchedFilesParams)
508 | -> GResult<()>
509 | {
510 | self.endpoint.send_notification(NOTIFICATION__DidChangeWatchedFiles, params)
511 | }
512 |
513 | fn completion(&mut self, params: TextDocumentPositionParams)
514 | -> GResult>
515 | {
516 | self.endpoint.send_request(REQUEST__Completion, params)
517 | }
518 |
519 | fn resolve_completion_item(&mut self, params: CompletionItem)
520 | -> GResult>
521 | {
522 | self.endpoint.send_request(REQUEST__ResolveCompletionItem, params)
523 | }
524 |
525 | fn hover(&mut self, params: TextDocumentPositionParams)
526 | -> GResult>
527 | {
528 | self.endpoint.send_request(REQUEST__Hover, params)
529 | }
530 |
531 | fn signature_help(&mut self, params: TextDocumentPositionParams)
532 | -> GResult>
533 | {
534 | self.endpoint.send_request(REQUEST__SignatureHelp, params)
535 | }
536 |
537 | fn goto_definition(&mut self, params: TextDocumentPositionParams)
538 | -> GResult, ()>>
539 | {
540 | self.endpoint.send_request(REQUEST__GotoDefinition, params)
541 | }
542 |
543 | fn references(&mut self, params: ReferenceParams)
544 | -> GResult, ()>>
545 | {
546 | self.endpoint.send_request(REQUEST__References, params)
547 | }
548 |
549 | fn document_highlight(&mut self, params: TextDocumentPositionParams)
550 | -> GResult, ()>>
551 | {
552 | self.endpoint.send_request(REQUEST__DocumentHighlight, params)
553 | }
554 |
555 | fn document_symbols(&mut self, params: DocumentSymbolParams)
556 | -> GResult, ()>>
557 | {
558 | self.endpoint.send_request(REQUEST__DocumentSymbols, params)
559 | }
560 |
561 | fn workspace_symbols(&mut self, params: WorkspaceSymbolParams)
562 | -> GResult, ()>>
563 | {
564 | self.endpoint.send_request(REQUEST__WorkspaceSymbols, params)
565 | }
566 |
567 | fn code_action(&mut self, params: CodeActionParams)
568 | -> GResult, ()>>
569 | {
570 | self.endpoint.send_request(REQUEST__CodeAction, params)
571 | }
572 |
573 | fn code_lens(&mut self, params: CodeLensParams)
574 | -> GResult, ()>>
575 | {
576 | self.endpoint.send_request(REQUEST__CodeLens, params)
577 | }
578 |
579 | fn code_lens_resolve(&mut self, params: CodeLens)
580 | -> GResult>
581 | {
582 | self.endpoint.send_request(REQUEST__CodeLensResolve, params)
583 | }
584 |
585 | fn formatting(&mut self, params: DocumentFormattingParams)
586 | -> GResult, ()>>
587 | {
588 | self.endpoint.send_request(REQUEST__Formatting, params)
589 | }
590 |
591 | fn range_formatting(&mut self, params: DocumentRangeFormattingParams)
592 | -> GResult, ()>>
593 | {
594 | self.endpoint.send_request(REQUEST__RangeFormatting, params)
595 | }
596 |
597 | fn on_type_formatting(&mut self, params: DocumentOnTypeFormattingParams)
598 | -> GResult, ()>>
599 | {
600 | self.endpoint.send_request(REQUEST__OnTypeFormatting, params)
601 | }
602 |
603 | fn rename(&mut self, params: RenameParams)
604 | -> GResult>
605 | {
606 | self.endpoint.send_request(REQUEST__Rename, params)
607 | }
608 |
609 | }
610 |
611 |
612 | /// Trait for the handling of LSP client requests.
613 | /// (An LSP server can act as a JSON-RPC Client and request to the LSP client)
614 | pub trait LanguageClientHandling {
615 |
616 | fn show_message(&mut self, params: ShowMessageParams);
617 |
618 | fn show_message_request(&mut self, params: ShowMessageRequestParams,
619 | completable: LSCompletable);
620 |
621 | fn log_message(&mut self, params: LogMessageParams);
622 |
623 | fn telemetry_event(&mut self, params: Value);
624 |
625 | fn publish_diagnostics(&mut self, params: PublishDiagnosticsParams);
626 |
627 | #[allow(unused_variables)]
628 | fn handle_other_method(&mut self, method_name: &str, params: RequestParams, completable: ResponseCompletable) {
629 | completable.complete_with_error(jsonrpc_common::error_JSON_RPC_MethodNotFound());
630 | }
631 |
632 | }
633 |
634 | pub struct ClientRequestHandler(pub LS);
635 |
636 | impl RequestHandler for ClientRequestHandler {
637 |
638 | fn handle_request(
639 | &mut self, method_name: &str, params: RequestParams, completable: ResponseCompletable
640 | ) {
641 | match method_name {
642 | NOTIFICATION__ShowMessage => {
643 | completable.handle_notification_with(params,
644 | |params| self.0.show_message(params))
645 | }
646 | REQUEST__ShowMessageRequest => {
647 | completable.handle_request_with(params,
648 | |params, completable| self.0.show_message_request(params, completable)
649 | )
650 | }
651 | NOTIFICATION__LogMessage => {
652 | completable.handle_notification_with(params,
653 | |params| self.0.log_message(params))
654 | }
655 | NOTIFICATION__TelemetryEvent => {
656 | completable.handle_notification_with(params,
657 | |params| self.0.telemetry_event(params)
658 | )
659 | }
660 | NOTIFICATION__PublishDiagnostics => {
661 | completable.handle_notification_with(params,
662 | |params| self.0.publish_diagnostics(params)
663 | )
664 | }
665 | _ => {
666 | self.0.handle_other_method(method_name, params, completable);
667 | }
668 | }
669 | }
670 |
671 | }
--------------------------------------------------------------------------------