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.rs6
-rw-r--r--crates/ra_lsp_server/src/conv.rs32
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs42
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs131
-rw-r--r--crates/ra_lsp_server/src/req.rs16
5 files changed, 189 insertions, 38 deletions
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs
index db502c200..c4711076c 100644
--- a/crates/ra_lsp_server/src/caps.rs
+++ b/crates/ra_lsp_server/src/caps.rs
@@ -1,8 +1,8 @@
1//! Advertizes the capabilities of the LSP Server. 1//! Advertizes the capabilities of the LSP Server.
2 2
3use lsp_types::{ 3use lsp_types::{
4 CodeActionProviderCapability, CodeLensOptions, CompletionOptions, 4 CallHierarchyServerCapability, CodeActionProviderCapability, CodeLensOptions,
5 DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, 5 CompletionOptions, DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability,
6 ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions, 6 ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions,
7 SelectionRangeProviderCapability, ServerCapabilities, SignatureHelpOptions, 7 SelectionRangeProviderCapability, ServerCapabilities, SignatureHelpOptions,
8 TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, 8 TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions,
@@ -56,7 +56,7 @@ pub fn server_capabilities() -> ServerCapabilities {
56 color_provider: None, 56 color_provider: None,
57 execute_command_provider: None, 57 execute_command_provider: None,
58 workspace: None, 58 workspace: None,
59 call_hierarchy_provider: None, 59 call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)),
60 experimental: Default::default(), 60 experimental: Default::default(),
61 } 61 }
62} 62}
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index e93d4ea33..562699b7c 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -9,7 +9,7 @@ use lsp_types::{
9use ra_ide::{ 9use ra_ide::{
10 translate_offset_with_edit, CompletionItem, CompletionItemKind, FileId, FilePosition, 10 translate_offset_with_edit, CompletionItem, CompletionItemKind, FileId, FilePosition,
11 FileRange, FileSystemEdit, Fold, FoldKind, InsertTextFormat, LineCol, LineIndex, 11 FileRange, FileSystemEdit, Fold, FoldKind, InsertTextFormat, LineCol, LineIndex,
12 NavigationTarget, RangeInfo, Severity, SourceChange, SourceFileEdit, 12 NavigationTarget, RangeInfo, ReferenceAccess, Severity, SourceChange, SourceFileEdit,
13}; 13};
14use ra_syntax::{SyntaxKind, TextRange, TextUnit}; 14use ra_syntax::{SyntaxKind, TextRange, TextUnit};
15use ra_text_edit::{AtomTextEdit, TextEdit}; 15use ra_text_edit::{AtomTextEdit, TextEdit};
@@ -53,6 +53,18 @@ impl Conv for SyntaxKind {
53 } 53 }
54} 54}
55 55
56impl Conv for ReferenceAccess {
57 type Output = ::lsp_types::DocumentHighlightKind;
58
59 fn conv(self) -> Self::Output {
60 use lsp_types::DocumentHighlightKind;
61 match self {
62 ReferenceAccess::Read => DocumentHighlightKind::Read,
63 ReferenceAccess::Write => DocumentHighlightKind::Write,
64 }
65 }
66}
67
56impl Conv for CompletionItemKind { 68impl Conv for CompletionItemKind {
57 type Output = ::lsp_types::CompletionItemKind; 69 type Output = ::lsp_types::CompletionItemKind;
58 70
@@ -490,6 +502,24 @@ impl TryConvWith<&WorldSnapshot> for (FileId, RangeInfo<Vec<NavigationTarget>>)
490 } 502 }
491} 503}
492 504
505pub fn to_call_hierarchy_item(
506 file_id: FileId,
507 range: TextRange,
508 world: &WorldSnapshot,
509 line_index: &LineIndex,
510 nav: NavigationTarget,
511) -> Result<lsp_types::CallHierarchyItem> {
512 Ok(lsp_types::CallHierarchyItem {
513 name: nav.name().to_string(),
514 kind: nav.kind().conv(),
515 tags: None,
516 detail: nav.description().map(|it| it.to_string()),
517 uri: file_id.try_conv_with(&world)?,
518 range: nav.range().conv_with(&line_index),
519 selection_range: range.conv_with(&line_index),
520 })
521}
522
493pub fn to_location( 523pub fn to_location(
494 file_id: FileId, 524 file_id: FileId,
495 range: TextRange, 525 range: TextRange,
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 4336583fe..7a49cad86 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -62,6 +62,22 @@ pub fn main_loop(
62 62
63 let mut loop_state = LoopState::default(); 63 let mut loop_state = LoopState::default();
64 let mut world_state = { 64 let mut world_state = {
65 let feature_flags = {
66 let mut ff = FeatureFlags::default();
67 for (flag, value) in config.feature_flags {
68 if ff.set(flag.as_str(), value).is_err() {
69 log::error!("unknown feature flag: {:?}", flag);
70 show_message(
71 req::MessageType::Error,
72 format!("unknown feature flag: {:?}", flag),
73 &connection.sender,
74 );
75 }
76 }
77 ff
78 };
79 log::info!("feature_flags: {:#?}", feature_flags);
80
65 // FIXME: support dynamic workspace loading. 81 // FIXME: support dynamic workspace loading.
66 let workspaces = { 82 let workspaces = {
67 let mut loaded_workspaces = Vec::new(); 83 let mut loaded_workspaces = Vec::new();
@@ -75,7 +91,12 @@ pub fn main_loop(
75 Ok(workspace) => loaded_workspaces.push(workspace), 91 Ok(workspace) => loaded_workspaces.push(workspace),
76 Err(e) => { 92 Err(e) => {
77 log::error!("loading workspace failed: {}", e); 93 log::error!("loading workspace failed: {}", e);
78 94 if let Some(ra_project_model::CargoTomlNotFoundError(_)) = e.downcast_ref()
95 {
96 if !feature_flags.get("notifications.cargo-toml-not-found") {
97 continue;
98 }
99 }
79 show_message( 100 show_message(
80 req::MessageType::Error, 101 req::MessageType::Error,
81 format!("rust-analyzer failed to load workspace: {}", e), 102 format!("rust-analyzer failed to load workspace: {}", e),
@@ -136,22 +157,6 @@ pub fn main_loop(
136 } 157 }
137 }; 158 };
138 159
139 let feature_flags = {
140 let mut ff = FeatureFlags::default();
141 for (flag, value) in config.feature_flags {
142 if ff.set(flag.as_str(), value).is_err() {
143 log::error!("unknown feature flag: {:?}", flag);
144 show_message(
145 req::MessageType::Error,
146 format!("unknown feature flag: {:?}", flag),
147 &connection.sender,
148 );
149 }
150 }
151 ff
152 };
153 log::info!("feature_flags: {:#?}", feature_flags);
154
155 WorldState::new( 160 WorldState::new(
156 ws_roots, 161 ws_roots,
157 workspaces, 162 workspaces,
@@ -499,6 +504,9 @@ fn on_request(
499 .on::<req::Formatting>(handlers::handle_formatting)? 504 .on::<req::Formatting>(handlers::handle_formatting)?
500 .on::<req::DocumentHighlightRequest>(handlers::handle_document_highlight)? 505 .on::<req::DocumentHighlightRequest>(handlers::handle_document_highlight)?
501 .on::<req::InlayHints>(handlers::handle_inlay_hints)? 506 .on::<req::InlayHints>(handlers::handle_inlay_hints)?
507 .on::<req::CallHierarchyPrepare>(handlers::handle_call_hierarchy_prepare)?
508 .on::<req::CallHierarchyIncomingCalls>(handlers::handle_call_hierarchy_incoming)?
509 .on::<req::CallHierarchyOutgoingCalls>(handlers::handle_call_hierarchy_outgoing)?
502 .finish(); 510 .finish();
503 Ok(()) 511 Ok(())
504} 512}
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 331beab13..a592f0a12 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -5,13 +5,16 @@ use std::{fmt::Write as _, io::Write as _};
5 5
6use lsp_server::ErrorCode; 6use lsp_server::ErrorCode;
7use lsp_types::{ 7use lsp_types::{
8 CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
9 CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams,
8 CodeAction, CodeActionResponse, CodeLens, Command, CompletionItem, Diagnostic, 10 CodeAction, CodeActionResponse, CodeLens, Command, CompletionItem, Diagnostic,
9 DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeParams, 11 DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeParams,
10 Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse, 12 Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse,
11 Range, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit, 13 Range, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit,
12}; 14};
13use ra_ide::{ 15use ra_ide::{
14 AssistId, FileId, FilePosition, FileRange, Query, Runnable, RunnableKind, SearchScope, 16 AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind,
17 SearchScope,
15}; 18};
16use ra_prof::profile; 19use ra_prof::profile;
17use ra_syntax::{AstNode, SyntaxKind, TextRange, TextUnit}; 20use ra_syntax::{AstNode, SyntaxKind, TextRange, TextUnit};
@@ -21,7 +24,10 @@ use serde_json::to_value;
21 24
22use crate::{ 25use crate::{
23 cargo_target_spec::{runnable_args, CargoTargetSpec}, 26 cargo_target_spec::{runnable_args, CargoTargetSpec},
24 conv::{to_location, Conv, ConvWith, FoldConvCtx, MapConvWith, TryConvWith, TryConvWithToVec}, 27 conv::{
28 to_call_hierarchy_item, to_location, Conv, ConvWith, FoldConvCtx, MapConvWith, TryConvWith,
29 TryConvWithToVec,
30 },
25 req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind}, 31 req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind},
26 world::WorldSnapshot, 32 world::WorldSnapshot,
27 LspError, Result, 33 LspError, Result,
@@ -530,18 +536,32 @@ pub fn handle_references(
530 536
531 let locations = if params.context.include_declaration { 537 let locations = if params.context.include_declaration {
532 refs.into_iter() 538 refs.into_iter()
533 .filter_map(|r| { 539 .filter_map(|reference| {
534 let line_index = world.analysis().file_line_index(r.file_id).ok()?; 540 let line_index =
535 to_location(r.file_id, r.range, &world, &line_index).ok() 541 world.analysis().file_line_index(reference.file_range.file_id).ok()?;
542 to_location(
543 reference.file_range.file_id,
544 reference.file_range.range,
545 &world,
546 &line_index,
547 )
548 .ok()
536 }) 549 })
537 .collect() 550 .collect()
538 } else { 551 } else {
539 // Only iterate over the references if include_declaration was false 552 // Only iterate over the references if include_declaration was false
540 refs.references() 553 refs.references()
541 .iter() 554 .iter()
542 .filter_map(|r| { 555 .filter_map(|reference| {
543 let line_index = world.analysis().file_line_index(r.file_id).ok()?; 556 let line_index =
544 to_location(r.file_id, r.range, &world, &line_index).ok() 557 world.analysis().file_line_index(reference.file_range.file_id).ok()?;
558 to_location(
559 reference.file_range.file_id,
560 reference.file_range.range,
561 &world,
562 &line_index,
563 )
564 .ok()
545 }) 565 })
546 .collect() 566 .collect()
547 }; 567 };
@@ -830,8 +850,11 @@ pub fn handle_document_highlight(
830 850
831 Ok(Some( 851 Ok(Some(
832 refs.into_iter() 852 refs.into_iter()
833 .filter(|r| r.file_id == file_id) 853 .filter(|reference| reference.file_range.file_id == file_id)
834 .map(|r| DocumentHighlight { range: r.range.conv_with(&line_index), kind: None }) 854 .map(|reference| DocumentHighlight {
855 range: reference.file_range.range.conv_with(&line_index),
856 kind: reference.access.map(|it| it.conv()),
857 })
835 .collect(), 858 .collect(),
836 )) 859 ))
837} 860}
@@ -933,3 +956,91 @@ pub fn handle_inlay_hints(
933 }) 956 })
934 .collect()) 957 .collect())
935} 958}
959
960pub fn handle_call_hierarchy_prepare(
961 world: WorldSnapshot,
962 params: CallHierarchyPrepareParams,
963) -> Result<Option<Vec<CallHierarchyItem>>> {
964 let _p = profile("handle_call_hierarchy_prepare");
965 let position = params.text_document_position_params.try_conv_with(&world)?;
966 let file_id = position.file_id;
967
968 let nav_info = match world.analysis().call_hierarchy(position)? {
969 None => return Ok(None),
970 Some(it) => it,
971 };
972
973 let line_index = world.analysis().file_line_index(file_id)?;
974 let RangeInfo { range, info: navs } = nav_info;
975 let res = navs
976 .into_iter()
977 .filter(|it| it.kind() == SyntaxKind::FN_DEF)
978 .filter_map(|it| to_call_hierarchy_item(file_id, range, &world, &line_index, it).ok())
979 .collect();
980
981 Ok(Some(res))
982}
983
984pub fn handle_call_hierarchy_incoming(
985 world: WorldSnapshot,
986 params: CallHierarchyIncomingCallsParams,
987) -> Result<Option<Vec<CallHierarchyIncomingCall>>> {
988 let _p = profile("handle_call_hierarchy_incoming");
989 let item = params.item;
990
991 let doc = TextDocumentIdentifier::new(item.uri);
992 let frange: FileRange = (&doc, item.range).try_conv_with(&world)?;
993 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
994
995 let call_items = match world.analysis().incoming_calls(fpos)? {
996 None => return Ok(None),
997 Some(it) => it,
998 };
999
1000 let mut res = vec![];
1001
1002 for call_item in call_items.into_iter() {
1003 let file_id = call_item.target.file_id();
1004 let line_index = world.analysis().file_line_index(file_id)?;
1005 let range = call_item.target.range();
1006 let item = to_call_hierarchy_item(file_id, range, &world, &line_index, call_item.target)?;
1007 res.push(CallHierarchyIncomingCall {
1008 from: item,
1009 from_ranges: call_item.ranges.iter().map(|it| it.conv_with(&line_index)).collect(),
1010 });
1011 }
1012
1013 Ok(Some(res))
1014}
1015
1016pub fn handle_call_hierarchy_outgoing(
1017 world: WorldSnapshot,
1018 params: CallHierarchyOutgoingCallsParams,
1019) -> Result<Option<Vec<CallHierarchyOutgoingCall>>> {
1020 let _p = profile("handle_call_hierarchy_outgoing");
1021 let item = params.item;
1022
1023 let doc = TextDocumentIdentifier::new(item.uri);
1024 let frange: FileRange = (&doc, item.range).try_conv_with(&world)?;
1025 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
1026
1027 let call_items = match world.analysis().outgoing_calls(fpos)? {
1028 None => return Ok(None),
1029 Some(it) => it,
1030 };
1031
1032 let mut res = vec![];
1033
1034 for call_item in call_items.into_iter() {
1035 let file_id = call_item.target.file_id();
1036 let line_index = world.analysis().file_line_index(file_id)?;
1037 let range = call_item.target.range();
1038 let item = to_call_hierarchy_item(file_id, range, &world, &line_index, call_item.target)?;
1039 res.push(CallHierarchyOutgoingCall {
1040 to: item,
1041 from_ranges: call_item.ranges.iter().map(|it| it.conv_with(&line_index)).collect(),
1042 });
1043 }
1044
1045 Ok(Some(res))
1046}
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs
index 40edaf677..8098ff31d 100644
--- a/crates/ra_lsp_server/src/req.rs
+++ b/crates/ra_lsp_server/src/req.rs
@@ -6,13 +6,15 @@ use serde::{Deserialize, Serialize};
6 6
7pub use lsp_types::{ 7pub use lsp_types::{
8 notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens, 8 notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens,
9 CodeLensParams, CompletionParams, CompletionResponse, DidChangeConfigurationParams, 9 CodeLensParams, CompletionParams, CompletionResponse, DiagnosticTag,
10 DidChangeWatchedFilesParams, DidChangeWatchedFilesRegistrationOptions, 10 DidChangeConfigurationParams, DidChangeWatchedFilesParams,
11 DocumentOnTypeFormattingParams, DocumentSymbolParams, DocumentSymbolResponse, 11 DidChangeWatchedFilesRegistrationOptions, DocumentOnTypeFormattingParams, DocumentSymbolParams,
12 FileSystemWatcher, Hover, InitializeResult, MessageType, ProgressParams, ProgressParamsValue, 12 DocumentSymbolResponse, FileSystemWatcher, Hover, InitializeResult, MessageType,
13 ProgressToken, PublishDiagnosticsParams, ReferenceParams, Registration, RegistrationParams, 13 PartialResultParams, ProgressParams, ProgressParamsValue, ProgressToken,
14 SelectionRange, SelectionRangeParams, ShowMessageParams, SignatureHelp, TextDocumentEdit, 14 PublishDiagnosticsParams, ReferenceParams, Registration, RegistrationParams, SelectionRange,
15 TextDocumentPositionParams, TextEdit, WorkspaceEdit, WorkspaceSymbolParams, 15 SelectionRangeParams, ServerCapabilities, ShowMessageParams, SignatureHelp, SymbolKind,
16 TextDocumentEdit, TextDocumentPositionParams, TextEdit, WorkDoneProgressParams, WorkspaceEdit,
17 WorkspaceSymbolParams,
16}; 18};
17 19
18pub enum AnalyzerStatus {} 20pub enum AnalyzerStatus {}