aboutsummaryrefslogtreecommitdiff
path: root/codeless/server/src/main.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-10 19:13:39 +0100
committerAleksey Kladov <[email protected]>2018-08-10 19:13:39 +0100
commit120789804d5483f14c9682b2b777adf6d2992547 (patch)
treebccbe4a72e648516f838499b91e5158484b5cbcd /codeless/server/src/main.rs
parent1be7af26a83b79863efb0d66a77b1fb7c0235bd2 (diff)
Add line index
Diffstat (limited to 'codeless/server/src/main.rs')
-rw-r--r--codeless/server/src/main.rs75
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;
19mod caps; 19mod caps;
20mod req; 20mod req;
21mod dispatch; 21mod dispatch;
22mod handlers;
23
24use std::path::PathBuf;
22 25
23use threadpool::ThreadPool; 26use threadpool::ThreadPool;
24use crossbeam_channel::{bounded, Sender, Receiver}; 27use crossbeam_channel::{bounded, Sender, Receiver};
25use flexi_logger::Logger; 28use flexi_logger::Logger;
26use libanalysis::WorldState; 29use libanalysis::WorldState;
30use languageserver_types::{TextDocumentItem, VersionedTextDocumentIdentifier, TextDocumentIdentifier};
27 31
28use ::{ 32use ::{
29 io::{Io, RawMsg}, 33 io::{Io, RawMsg},
34 handlers::handle_syntax_tree,
30}; 35};
31 36
32pub type Result<T> = ::std::result::Result<T, ::failure::Error>; 37pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
33 38
34fn main() -> Result<()> { 39fn 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
184trait FnBox<A, R>: Send { 208trait 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
218trait FilePath {
219 fn file_path(&self) -> Result<PathBuf>;
220}
221
222impl 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
229impl 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
236impl 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}