aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server/src')
-rw-r--r--crates/ra_lsp_server/src/caps.rs2
-rw-r--r--crates/ra_lsp_server/src/conv.rs23
-rw-r--r--crates/ra_lsp_server/src/main.rs41
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs28
-rw-r--r--crates/ra_lsp_server/src/main_loop/mod.rs24
5 files changed, 96 insertions, 22 deletions
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs
index 0d02c8073..bcf857fce 100644
--- a/crates/ra_lsp_server/src/caps.rs
+++ b/crates/ra_lsp_server/src/caps.rs
@@ -16,7 +16,7 @@ pub fn server_capabilities() -> ServerCapabilities {
16 save: None, 16 save: None,
17 }, 17 },
18 )), 18 )),
19 hover_provider: None, 19 hover_provider: Some(true),
20 completion_provider: Some(CompletionOptions { 20 completion_provider: Some(CompletionOptions {
21 resolve_provider: None, 21 resolve_provider: None,
22 trigger_characters: None, 22 trigger_characters: None,
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index fa04f4b00..5d5a0c55e 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -2,7 +2,7 @@ use languageserver_types::{
2 Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, 2 Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier,
3 TextDocumentItem, TextDocumentPositionParams, TextEdit, Url, VersionedTextDocumentIdentifier, 3 TextDocumentItem, TextDocumentPositionParams, TextEdit, Url, VersionedTextDocumentIdentifier,
4}; 4};
5use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileEdit, FilePosition}; 5use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileNodeEdit, FilePosition};
6use ra_editor::{AtomEdit, Edit, LineCol, LineIndex}; 6use ra_editor::{AtomEdit, Edit, LineCol, LineIndex};
7use ra_syntax::{SyntaxKind, TextRange, TextUnit}; 7use ra_syntax::{SyntaxKind, TextRange, TextUnit};
8 8
@@ -49,10 +49,9 @@ impl ConvWith for Position {
49 type Output = TextUnit; 49 type Output = TextUnit;
50 50
51 fn conv_with(self, line_index: &LineIndex) -> TextUnit { 51 fn conv_with(self, line_index: &LineIndex) -> TextUnit {
52 // TODO: UTF-16
53 let line_col = LineCol { 52 let line_col = LineCol {
54 line: self.line as u32, 53 line: self.line as u32,
55 col: (self.character as u32).into(), 54 col_utf16: self.character as u32,
56 }; 55 };
57 line_index.offset(line_col) 56 line_index.offset(line_col)
58 } 57 }
@@ -64,8 +63,10 @@ impl ConvWith for TextUnit {
64 63
65 fn conv_with(self, line_index: &LineIndex) -> Position { 64 fn conv_with(self, line_index: &LineIndex) -> Position {
66 let line_col = line_index.line_col(self); 65 let line_col = line_index.line_col(self);
67 // TODO: UTF-16 66 Position::new(
68 Position::new(u64::from(line_col.line), u64::from(u32::from(line_col.col))) 67 u64::from(line_col.line),
68 u64::from(u32::from(line_col.col_utf16)),
69 )
69 } 70 }
70} 71}
71 72
@@ -203,8 +204,10 @@ impl TryConvWith for SourceChange {
203 .map(|it| it.edits.as_slice()) 204 .map(|it| it.edits.as_slice())
204 .unwrap_or(&[]); 205 .unwrap_or(&[]);
205 let line_col = translate_offset_with_edit(&*line_index, pos.offset, edits); 206 let line_col = translate_offset_with_edit(&*line_index, pos.offset, edits);
206 let position = 207 let position = Position::new(
207 Position::new(u64::from(line_col.line), u64::from(u32::from(line_col.col))); 208 u64::from(line_col.line),
209 u64::from(u32::from(line_col.col_utf16)),
210 );
208 Some(TextDocumentPositionParams { 211 Some(TextDocumentPositionParams {
209 text_document: TextDocumentIdentifier::new(pos.file_id.try_conv_with(world)?), 212 text_document: TextDocumentIdentifier::new(pos.file_id.try_conv_with(world)?),
210 position, 213 position,
@@ -247,17 +250,17 @@ fn translate_offset_with_edit(
247 if in_edit_line_col.line == 0 { 250 if in_edit_line_col.line == 0 {
248 LineCol { 251 LineCol {
249 line: edit_line_col.line, 252 line: edit_line_col.line,
250 col: edit_line_col.col + in_edit_line_col.col, 253 col_utf16: edit_line_col.col_utf16 + in_edit_line_col.col_utf16,
251 } 254 }
252 } else { 255 } else {
253 LineCol { 256 LineCol {
254 line: edit_line_col.line + in_edit_line_col.line, 257 line: edit_line_col.line + in_edit_line_col.line,
255 col: in_edit_line_col.col, 258 col_utf16: in_edit_line_col.col_utf16,
256 } 259 }
257 } 260 }
258} 261}
259 262
260impl TryConvWith for SourceFileEdit { 263impl TryConvWith for SourceFileNodeEdit {
261 type Ctx = ServerWorld; 264 type Ctx = ServerWorld;
262 type Output = TextDocumentEdit; 265 type Output = TextDocumentEdit;
263 fn try_conv_with(self, world: &ServerWorld) -> Result<TextDocumentEdit> { 266 fn try_conv_with(self, world: &ServerWorld) -> Result<TextDocumentEdit> {
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index c07eb0140..26bcddd8e 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -2,10 +2,14 @@
2extern crate log; 2extern crate log;
3#[macro_use] 3#[macro_use]
4extern crate failure; 4extern crate failure;
5#[macro_use]
6extern crate serde_derive;
7extern crate serde;
5extern crate flexi_logger; 8extern crate flexi_logger;
6extern crate gen_lsp_server; 9extern crate gen_lsp_server;
7extern crate ra_lsp_server; 10extern crate ra_lsp_server;
8 11
12use serde::Deserialize;
9use flexi_logger::{Duplicate, Logger}; 13use flexi_logger::{Duplicate, Logger};
10use gen_lsp_server::{run_server, stdio_transport}; 14use gen_lsp_server::{run_server, stdio_transport};
11use ra_lsp_server::Result; 15use ra_lsp_server::Result;
@@ -30,6 +34,12 @@ fn main() -> Result<()> {
30 } 34 }
31} 35}
32 36
37#[derive(Deserialize)]
38#[serde(rename_all = "camelCase")]
39struct InitializationOptions {
40 publish_decorations: bool,
41}
42
33fn main_inner() -> Result<()> { 43fn main_inner() -> Result<()> {
34 let (receiver, sender, threads) = stdio_transport(); 44 let (receiver, sender, threads) = stdio_transport();
35 let cwd = ::std::env::current_dir()?; 45 let cwd = ::std::env::current_dir()?;
@@ -42,7 +52,12 @@ fn main_inner() -> Result<()> {
42 .root_uri 52 .root_uri
43 .and_then(|it| it.to_file_path().ok()) 53 .and_then(|it| it.to_file_path().ok())
44 .unwrap_or(cwd); 54 .unwrap_or(cwd);
45 ra_lsp_server::main_loop(false, root, r, s) 55 let publish_decorations = params
56 .initialization_options
57 .and_then(|v| InitializationOptions::deserialize(v).ok())
58 .map(|it| it.publish_decorations)
59 == Some(true);
60 ra_lsp_server::main_loop(false, root, publish_decorations, r, s)
46 }, 61 },
47 )?; 62 )?;
48 info!("shutting down IO..."); 63 info!("shutting down IO...");
@@ -50,3 +65,27 @@ fn main_inner() -> Result<()> {
50 info!("... IO is down"); 65 info!("... IO is down");
51 Ok(()) 66 Ok(())
52} 67}
68
69/*
70 (let ((backend (eglot-xref-backend)))
71 (mapcar
72 (lambda (xref)
73 (let ((loc (xref-item-location xref)))
74 (propertize
75 (concat
76 (when (xref-file-location-p loc)
77 (with-slots (file line column) loc
78 (format "%s:%s:%s:"
79 (propertize (file-relative-name file)
80 'face 'compilation-info)
81 (propertize (format "%s" line)
82 'face 'compilation-line
83 )
84 column)))
85 (xref-item-summary xref))
86 'xref xref)))
87 (xref-backend-apropos backend "Analysis"))
88 )
89
90
91*/
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 5314a333e..c872b0dc4 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -4,9 +4,9 @@ use gen_lsp_server::ErrorCode;
4use languageserver_types::{ 4use languageserver_types::{
5 CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic, 5 CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic,
6 DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind, 6 DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind,
7 FoldingRangeParams, InsertTextFormat, Location, MarkupContent, MarkupKind, Position, 7 FoldingRangeParams, InsertTextFormat, Location, MarkupContent, MarkupKind, MarkedString, Position,
8 PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, 8 PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit,
9 WorkspaceEdit, ParameterInformation, SignatureInformation, 9 WorkspaceEdit, ParameterInformation, SignatureInformation, Hover, HoverContents,
10}; 10};
11use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition}; 11use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition};
12use ra_syntax::text_utils::contains_offset_nonstrict; 12use ra_syntax::text_utils::contains_offset_nonstrict;
@@ -478,6 +478,30 @@ pub fn handle_signature_help(
478 } 478 }
479} 479}
480 480
481pub fn handle_hover(
482 world: ServerWorld,
483 params: req::TextDocumentPositionParams,
484) -> Result<Option<Hover>> {
485 let position = params.try_conv_with(&world)?;
486 let line_index = world.analysis().file_line_index(position.file_id);
487
488 for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? {
489 let range = symbol.node_range.conv_with(&line_index);
490 let comment = world.analysis.doc_comment_for(file_id, symbol)?;
491
492 if comment.is_some() {
493 let contents = HoverContents::Scalar(MarkedString::String(comment.unwrap()));
494
495 return Ok(Some(Hover {
496 contents,
497 range: Some(range),
498 }));
499 }
500 }
501
502 Ok(None)
503}
504
481pub fn handle_prepare_rename( 505pub fn handle_prepare_rename(
482 world: ServerWorld, 506 world: ServerWorld,
483 params: req::TextDocumentPositionParams, 507 params: req::TextDocumentPositionParams,
diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs
index 229d1b0f7..78d93741a 100644
--- a/crates/ra_lsp_server/src/main_loop/mod.rs
+++ b/crates/ra_lsp_server/src/main_loop/mod.rs
@@ -48,6 +48,7 @@ enum Task {
48pub fn main_loop( 48pub fn main_loop(
49 internal_mode: bool, 49 internal_mode: bool,
50 root: PathBuf, 50 root: PathBuf,
51 publish_decorations: bool,
51 msg_receiver: &Receiver<RawMessage>, 52 msg_receiver: &Receiver<RawMessage>,
52 msg_sender: &Sender<RawMessage>, 53 msg_sender: &Sender<RawMessage>,
53) -> Result<()> { 54) -> Result<()> {
@@ -67,6 +68,7 @@ pub fn main_loop(
67 let mut subs = Subscriptions::new(); 68 let mut subs = Subscriptions::new();
68 let main_res = main_loop_inner( 69 let main_res = main_loop_inner(
69 internal_mode, 70 internal_mode,
71 publish_decorations,
70 root, 72 root,
71 &pool, 73 &pool,
72 msg_sender, 74 msg_sender,
@@ -99,6 +101,7 @@ pub fn main_loop(
99 101
100fn main_loop_inner( 102fn main_loop_inner(
101 internal_mode: bool, 103 internal_mode: bool,
104 publish_decorations: bool,
102 ws_root: PathBuf, 105 ws_root: PathBuf,
103 pool: &ThreadPool, 106 pool: &ThreadPool,
104 msg_sender: &Sender<RawMessage>, 107 msg_sender: &Sender<RawMessage>,
@@ -210,6 +213,7 @@ fn main_loop_inner(
210 update_file_notifications_on_threadpool( 213 update_file_notifications_on_threadpool(
211 pool, 214 pool,
212 state.snapshot(), 215 state.snapshot(),
216 publish_decorations,
213 task_sender.clone(), 217 task_sender.clone(),
214 subs.subscriptions(), 218 subs.subscriptions(),
215 ) 219 )
@@ -259,6 +263,7 @@ fn on_request(
259 .on::<req::CodeActionRequest>(handlers::handle_code_action)? 263 .on::<req::CodeActionRequest>(handlers::handle_code_action)?
260 .on::<req::FoldingRangeRequest>(handlers::handle_folding_range)? 264 .on::<req::FoldingRangeRequest>(handlers::handle_folding_range)?
261 .on::<req::SignatureHelpRequest>(handlers::handle_signature_help)? 265 .on::<req::SignatureHelpRequest>(handlers::handle_signature_help)?
266 .on::<req::HoverRequest>(handlers::handle_hover)?
262 .on::<req::PrepareRenameRequest>(handlers::handle_prepare_rename)? 267 .on::<req::PrepareRenameRequest>(handlers::handle_prepare_rename)?
263 .on::<req::Rename>(handlers::handle_rename)? 268 .on::<req::Rename>(handlers::handle_rename)?
264 .on::<req::References>(handlers::handle_references)? 269 .on::<req::References>(handlers::handle_references)?
@@ -415,6 +420,7 @@ impl<'a> PoolDispatcher<'a> {
415fn update_file_notifications_on_threadpool( 420fn update_file_notifications_on_threadpool(
416 pool: &ThreadPool, 421 pool: &ThreadPool,
417 world: ServerWorld, 422 world: ServerWorld,
423 publish_decorations: bool,
418 sender: Sender<Task>, 424 sender: Sender<Task>,
419 subscriptions: Vec<FileId>, 425 subscriptions: Vec<FileId>,
420) { 426) {
@@ -431,15 +437,17 @@ fn update_file_notifications_on_threadpool(
431 sender.send(Task::Notify(not)); 437 sender.send(Task::Notify(not));
432 } 438 }
433 } 439 }
434 match handlers::publish_decorations(&world, file_id) { 440 if publish_decorations {
435 Err(e) => { 441 match handlers::publish_decorations(&world, file_id) {
436 if !is_canceled(&e) { 442 Err(e) => {
437 error!("failed to compute decorations: {:?}", e); 443 if !is_canceled(&e) {
444 error!("failed to compute decorations: {:?}", e);
445 }
446 }
447 Ok(params) => {
448 let not = RawNotification::new::<req::PublishDecorations>(&params);
449 sender.send(Task::Notify(not))
438 } 450 }
439 }
440 Ok(params) => {
441 let not = RawNotification::new::<req::PublishDecorations>(&params);
442 sender.send(Task::Notify(not))
443 } 451 }
444 } 452 }
445 } 453 }