diff options
Diffstat (limited to 'crates/ra_lsp_server/src')
-rw-r--r-- | crates/ra_lsp_server/src/caps.rs | 6 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/conv.rs | 18 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 42 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 98 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/req.rs | 16 |
5 files changed, 151 insertions, 29 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 | ||
3 | use lsp_types::{ | 3 | use 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..c260b51c4 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs | |||
@@ -490,6 +490,24 @@ impl TryConvWith<&WorldSnapshot> for (FileId, RangeInfo<Vec<NavigationTarget>>) | |||
490 | } | 490 | } |
491 | } | 491 | } |
492 | 492 | ||
493 | pub fn to_call_hierarchy_item( | ||
494 | file_id: FileId, | ||
495 | range: TextRange, | ||
496 | world: &WorldSnapshot, | ||
497 | line_index: &LineIndex, | ||
498 | nav: NavigationTarget, | ||
499 | ) -> Result<lsp_types::CallHierarchyItem> { | ||
500 | Ok(lsp_types::CallHierarchyItem { | ||
501 | name: nav.name().to_string(), | ||
502 | kind: nav.kind().conv(), | ||
503 | tags: None, | ||
504 | detail: nav.description().map(|it| it.to_string()), | ||
505 | uri: file_id.try_conv_with(&world)?, | ||
506 | range: nav.range().conv_with(&line_index), | ||
507 | selection_range: range.conv_with(&line_index), | ||
508 | }) | ||
509 | } | ||
510 | |||
493 | pub fn to_location( | 511 | pub fn to_location( |
494 | file_id: FileId, | 512 | file_id: FileId, |
495 | range: TextRange, | 513 | 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 c8f52eb0e..a5b6f48af 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 | ||
6 | use lsp_server::ErrorCode; | 6 | use lsp_server::ErrorCode; |
7 | use lsp_types::{ | 7 | use 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 | }; |
13 | use ra_ide::{ | 15 | use ra_ide::{ |
14 | AssistId, FileId, FilePosition, FileRange, Query, Runnable, RunnableKind, SearchScope, | 16 | AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, |
17 | SearchScope, | ||
15 | }; | 18 | }; |
16 | use ra_prof::profile; | 19 | use ra_prof::profile; |
17 | use ra_syntax::{AstNode, SyntaxKind, TextRange, TextUnit}; | 20 | use ra_syntax::{AstNode, SyntaxKind, TextRange, TextUnit}; |
@@ -21,7 +24,10 @@ use serde_json::to_value; | |||
21 | 24 | ||
22 | use crate::{ | 25 | use 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, |
@@ -936,3 +942,91 @@ pub fn handle_inlay_hints( | |||
936 | }) | 942 | }) |
937 | .collect()) | 943 | .collect()) |
938 | } | 944 | } |
945 | |||
946 | pub fn handle_call_hierarchy_prepare( | ||
947 | world: WorldSnapshot, | ||
948 | params: CallHierarchyPrepareParams, | ||
949 | ) -> Result<Option<Vec<CallHierarchyItem>>> { | ||
950 | let _p = profile("handle_call_hierarchy_prepare"); | ||
951 | let position = params.text_document_position_params.try_conv_with(&world)?; | ||
952 | let file_id = position.file_id; | ||
953 | |||
954 | let nav_info = match world.analysis().call_hierarchy(position)? { | ||
955 | None => return Ok(None), | ||
956 | Some(it) => it, | ||
957 | }; | ||
958 | |||
959 | let line_index = world.analysis().file_line_index(file_id)?; | ||
960 | let RangeInfo { range, info: navs } = nav_info; | ||
961 | let res = navs | ||
962 | .into_iter() | ||
963 | .filter(|it| it.kind() == SyntaxKind::FN_DEF) | ||
964 | .filter_map(|it| to_call_hierarchy_item(file_id, range, &world, &line_index, it).ok()) | ||
965 | .collect(); | ||
966 | |||
967 | Ok(Some(res)) | ||
968 | } | ||
969 | |||
970 | pub fn handle_call_hierarchy_incoming( | ||
971 | world: WorldSnapshot, | ||
972 | params: CallHierarchyIncomingCallsParams, | ||
973 | ) -> Result<Option<Vec<CallHierarchyIncomingCall>>> { | ||
974 | let _p = profile("handle_call_hierarchy_incoming"); | ||
975 | let item = params.item; | ||
976 | |||
977 | let doc = TextDocumentIdentifier::new(item.uri); | ||
978 | let frange: FileRange = (&doc, item.range).try_conv_with(&world)?; | ||
979 | let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; | ||
980 | |||
981 | let call_items = match world.analysis().incoming_calls(fpos)? { | ||
982 | None => return Ok(None), | ||
983 | Some(it) => it, | ||
984 | }; | ||
985 | |||
986 | let mut res = vec![]; | ||
987 | |||
988 | for call_item in call_items.into_iter() { | ||
989 | let file_id = call_item.target.file_id(); | ||
990 | let line_index = world.analysis().file_line_index(file_id)?; | ||
991 | let range = call_item.target.range(); | ||
992 | let item = to_call_hierarchy_item(file_id, range, &world, &line_index, call_item.target)?; | ||
993 | res.push(CallHierarchyIncomingCall { | ||
994 | from: item, | ||
995 | from_ranges: call_item.ranges.iter().map(|it| it.conv_with(&line_index)).collect(), | ||
996 | }); | ||
997 | } | ||
998 | |||
999 | Ok(Some(res)) | ||
1000 | } | ||
1001 | |||
1002 | pub fn handle_call_hierarchy_outgoing( | ||
1003 | world: WorldSnapshot, | ||
1004 | params: CallHierarchyOutgoingCallsParams, | ||
1005 | ) -> Result<Option<Vec<CallHierarchyOutgoingCall>>> { | ||
1006 | let _p = profile("handle_call_hierarchy_outgoing"); | ||
1007 | let item = params.item; | ||
1008 | |||
1009 | let doc = TextDocumentIdentifier::new(item.uri); | ||
1010 | let frange: FileRange = (&doc, item.range).try_conv_with(&world)?; | ||
1011 | let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; | ||
1012 | |||
1013 | let call_items = match world.analysis().outgoing_calls(fpos)? { | ||
1014 | None => return Ok(None), | ||
1015 | Some(it) => it, | ||
1016 | }; | ||
1017 | |||
1018 | let mut res = vec![]; | ||
1019 | |||
1020 | for call_item in call_items.into_iter() { | ||
1021 | let file_id = call_item.target.file_id(); | ||
1022 | let line_index = world.analysis().file_line_index(file_id)?; | ||
1023 | let range = call_item.target.range(); | ||
1024 | let item = to_call_hierarchy_item(file_id, range, &world, &line_index, call_item.target)?; | ||
1025 | res.push(CallHierarchyOutgoingCall { | ||
1026 | to: item, | ||
1027 | from_ranges: call_item.ranges.iter().map(|it| it.conv_with(&line_index)).collect(), | ||
1028 | }); | ||
1029 | } | ||
1030 | |||
1031 | Ok(Some(res)) | ||
1032 | } | ||
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 | ||
7 | pub use lsp_types::{ | 7 | pub 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 | ||
18 | pub enum AnalyzerStatus {} | 20 | pub enum AnalyzerStatus {} |