diff options
author | Aleksey Kladov <[email protected]> | 2018-08-10 19:13:39 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-10 19:13:39 +0100 |
commit | 120789804d5483f14c9682b2b777adf6d2992547 (patch) | |
tree | bccbe4a72e648516f838499b91e5158484b5cbcd /codeless/server/src/main.rs | |
parent | 1be7af26a83b79863efb0d66a77b1fb7c0235bd2 (diff) |
Add line index
Diffstat (limited to 'codeless/server/src/main.rs')
-rw-r--r-- | codeless/server/src/main.rs | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/codeless/server/src/main.rs b/codeless/server/src/main.rs index fdb2fe2d5..287d650fa 100644 --- a/codeless/server/src/main.rs +++ b/codeless/server/src/main.rs | |||
@@ -19,20 +19,25 @@ mod io; | |||
19 | mod caps; | 19 | mod caps; |
20 | mod req; | 20 | mod req; |
21 | mod dispatch; | 21 | mod dispatch; |
22 | mod handlers; | ||
23 | |||
24 | use std::path::PathBuf; | ||
22 | 25 | ||
23 | use threadpool::ThreadPool; | 26 | use threadpool::ThreadPool; |
24 | use crossbeam_channel::{bounded, Sender, Receiver}; | 27 | use crossbeam_channel::{bounded, Sender, Receiver}; |
25 | use flexi_logger::Logger; | 28 | use flexi_logger::Logger; |
26 | use libanalysis::WorldState; | 29 | use libanalysis::WorldState; |
30 | use languageserver_types::{TextDocumentItem, VersionedTextDocumentIdentifier, TextDocumentIdentifier}; | ||
27 | 31 | ||
28 | use ::{ | 32 | use ::{ |
29 | io::{Io, RawMsg}, | 33 | io::{Io, RawMsg}, |
34 | handlers::handle_syntax_tree, | ||
30 | }; | 35 | }; |
31 | 36 | ||
32 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; | 37 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; |
33 | 38 | ||
34 | fn main() -> Result<()> { | 39 | fn main() -> Result<()> { |
35 | Logger::with_env_or_str("m=trace") | 40 | Logger::with_env_or_str("m=trace, libanalysis=trace") |
36 | .log_to_file() | 41 | .log_to_file() |
37 | .directory("log") | 42 | .directory("log") |
38 | .start()?; | 43 | .start()?; |
@@ -70,7 +75,7 @@ fn initialize(io: &mut Io) -> Result<()> { | |||
70 | loop { | 75 | loop { |
71 | match io.recv()? { | 76 | match io.recv()? { |
72 | RawMsg::Request(req) => { | 77 | RawMsg::Request(req) => { |
73 | if let Some((_params, resp)) = dispatch::expect::<req::Initialize>(io, req)? { | 78 | if let Some((_params, resp)) = dispatch::expect_request::<req::Initialize>(io, req)? { |
74 | resp.result(io, req::InitializeResult { | 79 | resp.result(io, req::InitializeResult { |
75 | capabilities: caps::SERVER_CAPABILITIES | 80 | capabilities: caps::SERVER_CAPABILITIES |
76 | })?; | 81 | })?; |
@@ -148,18 +153,12 @@ fn main_loop( | |||
148 | 153 | ||
149 | match msg { | 154 | match msg { |
150 | RawMsg::Request(req) => { | 155 | RawMsg::Request(req) => { |
151 | let req = match dispatch::parse_as::<req::SyntaxTree>(req)? { | 156 | let req = match dispatch::parse_request_as::<req::SyntaxTree>(req)? { |
152 | Ok((params, resp)) => { | 157 | Ok((params, resp)) => { |
153 | let world = world.snapshot(); | 158 | let world = world.snapshot(); |
154 | let sender = sender.clone(); | 159 | let sender = sender.clone(); |
155 | pool.execute(move || { | 160 | pool.execute(move || { |
156 | let res: Result<String> = (|| { | 161 | let res: Result<String> = handle_syntax_tree(world, params); |
157 | let path = params.text_document.uri.to_file_path() | ||
158 | .map_err(|()| format_err!("invalid path"))?; | ||
159 | let file = world.file_syntax(&path)?; | ||
160 | Ok(libeditor::syntax_tree(&file)) | ||
161 | })(); | ||
162 | |||
163 | sender.send(Box::new(|io: &mut Io| resp.response(io, res))) | 162 | sender.send(Box::new(|io: &mut Io| resp.response(io, res))) |
164 | }); | 163 | }); |
165 | continue; | 164 | continue; |
@@ -167,12 +166,38 @@ fn main_loop( | |||
167 | Err(req) => req, | 166 | Err(req) => req, |
168 | }; | 167 | }; |
169 | 168 | ||
170 | if let Some(((), resp)) = dispatch::expect::<req::Shutdown>(io, req)? { | 169 | if let Some(((), resp)) = dispatch::expect_request::<req::Shutdown>(io, req)? { |
171 | info!("shutdown request"); | 170 | info!("clean shutdown started"); |
172 | resp.result(io, ())?; | 171 | resp.result(io, ())?; |
173 | return Ok(()); | 172 | return Ok(()); |
174 | } | 173 | } |
175 | } | 174 | } |
175 | RawMsg::Notification(not) => { | ||
176 | use dispatch::handle_notification as h; | ||
177 | let mut not = Some(not); | ||
178 | h::<req::DidOpenTextDocument, _>(&mut not, |params| { | ||
179 | let path = params.text_document.file_path()?; | ||
180 | world.change_overlay(path, Some(params.text_document.text)); | ||
181 | Ok(()) | ||
182 | })?; | ||
183 | h::<req::DidChangeTextDocument, _>(&mut not, |mut params| { | ||
184 | let path = params.text_document.file_path()?; | ||
185 | let text = params.content_changes.pop() | ||
186 | .ok_or_else(|| format_err!("empty changes"))? | ||
187 | .text; | ||
188 | world.change_overlay(path, Some(text)); | ||
189 | Ok(()) | ||
190 | })?; | ||
191 | h::<req::DidCloseTextDocument, _>(&mut not, |params| { | ||
192 | let path = params.text_document.file_path()?; | ||
193 | world.change_overlay(path, None); | ||
194 | Ok(()) | ||
195 | })?; | ||
196 | |||
197 | if let Some(not) = not { | ||
198 | error!("unhandled notification: {:?}", not) | ||
199 | } | ||
200 | } | ||
176 | msg => { | 201 | msg => { |
177 | eprintln!("msg = {:?}", msg); | 202 | eprintln!("msg = {:?}", msg); |
178 | } | 203 | } |
@@ -180,7 +205,6 @@ fn main_loop( | |||
180 | } | 205 | } |
181 | } | 206 | } |
182 | 207 | ||
183 | |||
184 | trait FnBox<A, R>: Send { | 208 | trait FnBox<A, R>: Send { |
185 | fn call_box(self: Box<Self>, a: A) -> R; | 209 | fn call_box(self: Box<Self>, a: A) -> R; |
186 | } | 210 | } |
@@ -190,3 +214,28 @@ impl<A, R, F: FnOnce(A) -> R + Send> FnBox<A, R> for F { | |||
190 | (*self)(a) | 214 | (*self)(a) |
191 | } | 215 | } |
192 | } | 216 | } |
217 | |||
218 | trait FilePath { | ||
219 | fn file_path(&self) -> Result<PathBuf>; | ||
220 | } | ||
221 | |||
222 | impl FilePath for TextDocumentItem { | ||
223 | fn file_path(&self) -> Result<PathBuf> { | ||
224 | self.uri.to_file_path() | ||
225 | .map_err(|()| format_err!("invalid uri: {}", self.uri)) | ||
226 | } | ||
227 | } | ||
228 | |||
229 | impl FilePath for VersionedTextDocumentIdentifier { | ||
230 | fn file_path(&self) -> Result<PathBuf> { | ||
231 | self.uri.to_file_path() | ||
232 | .map_err(|()| format_err!("invalid uri: {}", self.uri)) | ||
233 | } | ||
234 | } | ||
235 | |||
236 | impl FilePath for TextDocumentIdentifier { | ||
237 | fn file_path(&self) -> Result<PathBuf> { | ||
238 | self.uri.to_file_path() | ||
239 | .map_err(|()| format_err!("invalid uri: {}", self.uri)) | ||
240 | } | ||
241 | } | ||