aboutsummaryrefslogtreecommitdiff
path: root/crates/server/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-10 21:30:11 +0100
committerAleksey Kladov <[email protected]>2018-08-10 21:30:11 +0100
commit36d922c87d0c933803441bde825ace5658af78b2 (patch)
tree3c14a27b678cc01a02c04be04784b21b4366e964 /crates/server/src
parent5896cd51de65cb6f7b8f3a4df85c4eb8886b76e2 (diff)
diagnostics
Diffstat (limited to 'crates/server/src')
-rw-r--r--crates/server/src/dispatch.rs12
-rw-r--r--crates/server/src/handlers.rs21
-rw-r--r--crates/server/src/main.rs53
-rw-r--r--crates/server/src/req.rs2
4 files changed, 79 insertions, 9 deletions
diff --git a/crates/server/src/dispatch.rs b/crates/server/src/dispatch.rs
index 2da0996e3..d9681db40 100644
--- a/crates/server/src/dispatch.rs
+++ b/crates/server/src/dispatch.rs
@@ -136,6 +136,18 @@ pub fn handle_notification<N, F>(not: &mut Option<RawNotification>, f: F) -> Res
136 } 136 }
137} 137}
138 138
139pub fn send_notification<N>(io: &mut Io, params: N::Params) -> Result<()>
140 where
141 N: Notification,
142 N::Params: Serialize
143{
144 io.send(RawMsg::Notification(RawNotification {
145 method: N::METHOD.to_string(),
146 params: serde_json::to_value(params)?,
147 }));
148 Ok(())
149}
150
139 151
140pub fn unknown_method(io: &mut Io, raw: RawRequest) -> Result<()> { 152pub fn unknown_method(io: &mut Io, raw: RawRequest) -> Result<()> {
141 error(io, raw.id, ErrorCode::MethodNotFound, "unknown method") 153 error(io, raw.id, ErrorCode::MethodNotFound, "unknown method")
diff --git a/crates/server/src/handlers.rs b/crates/server/src/handlers.rs
index 5ee87a4dd..1f55e8669 100644
--- a/crates/server/src/handlers.rs
+++ b/crates/server/src/handlers.rs
@@ -1,6 +1,8 @@
1use languageserver_types::{Range, Position}; 1use url::Url;
2use languageserver_types::{Range, Position, Diagnostic, DiagnosticSeverity};
2use libanalysis::World; 3use libanalysis::World;
3use libeditor::{self, LineIndex, LineCol, TextRange, TextUnit}; 4use libeditor::{self, LineIndex, LineCol, TextRange, TextUnit};
5
4use {req, Result, FilePath}; 6use {req, Result, FilePath};
5 7
6pub fn handle_syntax_tree( 8pub fn handle_syntax_tree(
@@ -29,6 +31,23 @@ pub fn handle_extend_selection(
29 Ok(req::ExtendSelectionResult { selections }) 31 Ok(req::ExtendSelectionResult { selections })
30} 32}
31 33
34pub fn publish_diagnostics(world: World, uri: Url) -> Result<req::PublishDiagnosticsParams> {
35 let path = uri.file_path()?;
36 let file = world.file_syntax(&path)?;
37 let line_index = world.file_line_index(&path)?;
38 let diagnostics = libeditor::diagnostics(&file)
39 .into_iter()
40 .map(|d| Diagnostic {
41 range: to_vs_range(&line_index, d.range),
42 severity: Some(DiagnosticSeverity::Error),
43 code: None,
44 source: Some("libsyntax2".to_string()),
45 message: d.msg,
46 related_information: None,
47 }).collect();
48 Ok(req::PublishDiagnosticsParams { uri, diagnostics })
49}
50
32 51
33fn to_text_range(line_index: &LineIndex, range: Range) -> TextRange { 52fn to_text_range(line_index: &LineIndex, range: Range) -> TextRange {
34 TextRange::from_to( 53 TextRange::from_to(
diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs
index 2d8695d23..6018350e3 100644
--- a/crates/server/src/main.rs
+++ b/crates/server/src/main.rs
@@ -11,6 +11,7 @@ extern crate crossbeam_channel;
11extern crate threadpool; 11extern crate threadpool;
12#[macro_use] 12#[macro_use]
13extern crate log; 13extern crate log;
14extern crate url;
14extern crate flexi_logger; 15extern crate flexi_logger;
15extern crate libeditor; 16extern crate libeditor;
16extern crate libanalysis; 17extern crate libanalysis;
@@ -31,7 +32,7 @@ use languageserver_types::{TextDocumentItem, VersionedTextDocumentIdentifier, Te
31 32
32use ::{ 33use ::{
33 io::{Io, RawMsg}, 34 io::{Io, RawMsg},
34 handlers::{handle_syntax_tree, handle_extend_selection}, 35 handlers::{handle_syntax_tree, handle_extend_selection, publish_diagnostics},
35}; 36};
36 37
37pub type Result<T> = ::std::result::Result<T, ::failure::Error>; 38pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
@@ -209,6 +210,21 @@ fn main_loop(
209 dispatch::handle_notification::<req::DidOpenTextDocument, _>(&mut not, |params| { 210 dispatch::handle_notification::<req::DidOpenTextDocument, _>(&mut not, |params| {
210 let path = params.text_document.file_path()?; 211 let path = params.text_document.file_path()?;
211 world.change_overlay(path, Some(params.text_document.text)); 212 world.change_overlay(path, Some(params.text_document.text));
213 let world = world.snapshot();
214 let sender = sender.clone();
215 let uri = params.text_document.uri;
216 pool.execute(move || {
217 match publish_diagnostics(world, uri) {
218 Err(e) => {
219 error!("failed to compute diagnostics: {:?}", e)
220 }
221 Ok(params) => {
222 sender.send(Box::new(|io: &mut Io| {
223 dispatch::send_notification::<req::PublishDiagnostics>(io, params)
224 }))
225 }
226 }
227 });
212 Ok(()) 228 Ok(())
213 })?; 229 })?;
214 dispatch::handle_notification::<req::DidChangeTextDocument, _>(&mut not, |mut params| { 230 dispatch::handle_notification::<req::DidChangeTextDocument, _>(&mut not, |mut params| {
@@ -217,11 +233,30 @@ fn main_loop(
217 .ok_or_else(|| format_err!("empty changes"))? 233 .ok_or_else(|| format_err!("empty changes"))?
218 .text; 234 .text;
219 world.change_overlay(path, Some(text)); 235 world.change_overlay(path, Some(text));
236 let world = world.snapshot();
237 let sender = sender.clone();
238 let uri = params.text_document.uri;
239 pool.execute(move || {
240 match publish_diagnostics(world, uri) {
241 Err(e) => {
242 error!("failed to compute diagnostics: {:?}", e)
243 }
244 Ok(params) => {
245 sender.send(Box::new(|io: &mut Io| {
246 dispatch::send_notification::<req::PublishDiagnostics>(io, params)
247 }))
248 }
249 }
250 });
220 Ok(()) 251 Ok(())
221 })?; 252 })?;
222 dispatch::handle_notification::<req::DidCloseTextDocument, _>(&mut not, |params| { 253 dispatch::handle_notification::<req::DidCloseTextDocument, _>(&mut not, |params| {
223 let path = params.text_document.file_path()?; 254 let path = params.text_document.file_path()?;
224 world.change_overlay(path, None); 255 world.change_overlay(path, None);
256 dispatch::send_notification::<req::PublishDiagnostics>(io, req::PublishDiagnosticsParams {
257 uri: params.text_document.uri,
258 diagnostics: Vec::new(),
259 })?;
225 Ok(()) 260 Ok(())
226 })?; 261 })?;
227 262
@@ -252,21 +287,25 @@ trait FilePath {
252 287
253impl FilePath for TextDocumentItem { 288impl FilePath for TextDocumentItem {
254 fn file_path(&self) -> Result<PathBuf> { 289 fn file_path(&self) -> Result<PathBuf> {
255 self.uri.to_file_path() 290 self.uri.file_path()
256 .map_err(|()| format_err!("invalid uri: {}", self.uri))
257 } 291 }
258} 292}
259 293
260impl FilePath for VersionedTextDocumentIdentifier { 294impl FilePath for VersionedTextDocumentIdentifier {
261 fn file_path(&self) -> Result<PathBuf> { 295 fn file_path(&self) -> Result<PathBuf> {
262 self.uri.to_file_path() 296 self.uri.file_path()
263 .map_err(|()| format_err!("invalid uri: {}", self.uri))
264 } 297 }
265} 298}
266 299
267impl FilePath for TextDocumentIdentifier { 300impl FilePath for TextDocumentIdentifier {
268 fn file_path(&self) -> Result<PathBuf> { 301 fn file_path(&self) -> Result<PathBuf> {
269 self.uri.to_file_path() 302 self.uri.file_path()
270 .map_err(|()| format_err!("invalid uri: {}", self.uri)) 303 }
304}
305
306impl FilePath for ::url::Url {
307 fn file_path(&self) -> Result<PathBuf> {
308 self.to_file_path()
309 .map_err(|()| format_err!("invalid uri: {}", self))
271 } 310 }
272} 311}
diff --git a/crates/server/src/req.rs b/crates/server/src/req.rs
index 4e588159b..64e7ef4ae 100644
--- a/crates/server/src/req.rs
+++ b/crates/server/src/req.rs
@@ -2,7 +2,7 @@ use languageserver_types::{TextDocumentIdentifier, Range};
2 2
3pub use languageserver_types::{ 3pub use languageserver_types::{
4 request::*, notification::*, 4 request::*, notification::*,
5 InitializeResult, 5 InitializeResult, PublishDiagnosticsParams
6}; 6};
7 7
8pub enum SyntaxTree {} 8pub enum SyntaxTree {}