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 | 32 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 42 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 131 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/req.rs | 16 |
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 | ||
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..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::{ | |||
9 | use ra_ide::{ | 9 | use 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 | }; |
14 | use ra_syntax::{SyntaxKind, TextRange, TextUnit}; | 14 | use ra_syntax::{SyntaxKind, TextRange, TextUnit}; |
15 | use ra_text_edit::{AtomTextEdit, TextEdit}; | 15 | use ra_text_edit::{AtomTextEdit, TextEdit}; |
@@ -53,6 +53,18 @@ impl Conv for SyntaxKind { | |||
53 | } | 53 | } |
54 | } | 54 | } |
55 | 55 | ||
56 | impl 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 | |||
56 | impl Conv for CompletionItemKind { | 68 | impl 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 | ||
505 | pub 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 | |||
493 | pub fn to_location( | 523 | pub 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 | ||
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, |
@@ -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 | |||
960 | pub 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 | |||
984 | pub 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 | |||
1016 | pub 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 | ||
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 {} |