aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-05-01 19:57:55 +0100
committerGitHub <[email protected]>2020-05-01 19:57:55 +0100
commit26079c7f2cce4cd1a2e833a045fb14377fa737d3 (patch)
tree07da881c1daeb65ea8e8683c367acc56e23cf322 /crates
parent4d33cdcfb2e06088c8bccc57565224f8a377d899 (diff)
parent99826dab153feffc8fe0d80600d9e812824d67b2 (diff)
Merge #4167
4167: Filter out code actions if unsupported by the client and advertise our capabilities r=matklad a=kjeremy This PR does three things: 1. If the client does not support `CodeActionKind` this will filter the results and only send `Command[]` back. 2. Correctly advertises to the client that the server supports `CodeActionKind`. This may cause clients to not request code actions if they are checking for the provider to be `true` (or implement LSP < 3.8) in the caps but I will fix that in a followup PR. 3. Marks most CodeActions as <strike>"refactor" so that they show up in the menu in vscode.</strike>`""`. Part of #144 #4147 #2833 Co-authored-by: kjeremy <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/rust-analyzer/src/caps.rs29
-rw-r--r--crates/rust-analyzer/src/config.rs6
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs28
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/support.rs6
4 files changed, 51 insertions, 18 deletions
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index e22ab8402..c0d320926 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -3,13 +3,13 @@
3use crate::semantic_tokens; 3use crate::semantic_tokens;
4 4
5use lsp_types::{ 5use lsp_types::{
6 CallHierarchyServerCapability, CodeActionProviderCapability, CodeLensOptions, 6 CallHierarchyServerCapability, CodeActionOptions, CodeActionProviderCapability,
7 CompletionOptions, DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, 7 CodeLensOptions, CompletionOptions, DocumentOnTypeFormattingOptions,
8 ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions, 8 FoldingRangeProviderCapability, ImplementationProviderCapability, RenameOptions,
9 SelectionRangeProviderCapability, SemanticTokensDocumentProvider, SemanticTokensLegend, 9 RenameProviderCapability, SaveOptions, SelectionRangeProviderCapability,
10 SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, 10 SemanticTokensDocumentProvider, SemanticTokensLegend, SemanticTokensOptions,
11 TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability, 11 ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
12 WorkDoneProgressOptions, 12 TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions,
13}; 13};
14 14
15pub fn server_capabilities() -> ServerCapabilities { 15pub fn server_capabilities() -> ServerCapabilities {
@@ -40,7 +40,20 @@ pub fn server_capabilities() -> ServerCapabilities {
40 document_highlight_provider: Some(true), 40 document_highlight_provider: Some(true),
41 document_symbol_provider: Some(true), 41 document_symbol_provider: Some(true),
42 workspace_symbol_provider: Some(true), 42 workspace_symbol_provider: Some(true),
43 code_action_provider: Some(CodeActionProviderCapability::Simple(true)), 43 code_action_provider: Some(CodeActionProviderCapability::Options(CodeActionOptions {
44 // Advertise support for all built-in CodeActionKinds
45 code_action_kinds: Some(vec![
46 String::new(),
47 lsp_types::code_action_kind::QUICKFIX.to_string(),
48 lsp_types::code_action_kind::REFACTOR.to_string(),
49 lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(),
50 lsp_types::code_action_kind::REFACTOR_INLINE.to_string(),
51 lsp_types::code_action_kind::REFACTOR_REWRITE.to_string(),
52 lsp_types::code_action_kind::SOURCE.to_string(),
53 lsp_types::code_action_kind::SOURCE_ORGANIZE_IMPORTS.to_string(),
54 ]),
55 work_done_progress_options: Default::default(),
56 })),
44 code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }), 57 code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
45 document_formatting_provider: Some(true), 58 document_formatting_provider: Some(true),
46 document_range_formatting_provider: None, 59 document_range_formatting_provider: None,
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 74a63e32a..177da94cc 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -70,6 +70,7 @@ pub struct ClientCapsConfig {
70 pub location_link: bool, 70 pub location_link: bool,
71 pub line_folding_only: bool, 71 pub line_folding_only: bool,
72 pub hierarchical_symbols: bool, 72 pub hierarchical_symbols: bool,
73 pub code_action_literals: bool,
73} 74}
74 75
75impl Default for Config { 76impl Default for Config {
@@ -221,6 +222,11 @@ impl Config {
221 { 222 {
222 self.client_caps.hierarchical_symbols = value 223 self.client_caps.hierarchical_symbols = value
223 } 224 }
225 if let Some(value) =
226 caps.code_action.as_ref().and_then(|it| Some(it.code_action_literal_support.is_some()))
227 {
228 self.client_caps.code_action_literals = value;
229 }
224 self.completion.allow_snippets(false); 230 self.completion.allow_snippets(false);
225 if let Some(completion) = &caps.completion { 231 if let Some(completion) = &caps.completion {
226 if let Some(completion_item) = &completion.completion_item { 232 if let Some(completion_item) = &completion.completion_item {
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 8db2dfa0c..0f623949e 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -19,8 +19,7 @@ use lsp_types::{
19 TextEdit, Url, WorkspaceEdit, 19 TextEdit, Url, WorkspaceEdit,
20}; 20};
21use ra_ide::{ 21use ra_ide::{
22 Assist, AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, 22 Assist, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, SearchScope,
23 SearchScope,
24}; 23};
25use ra_prof::profile; 24use ra_prof::profile;
26use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize}; 25use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize};
@@ -702,15 +701,9 @@ fn create_single_code_action(assist: Assist, world: &WorldSnapshot) -> Result<Co
702 arguments: Some(vec![arg]), 701 arguments: Some(vec![arg]),
703 }; 702 };
704 703
705 let kind = match assist.id {
706 AssistId("introduce_variable") => Some("refactor.extract.variable".to_string()),
707 AssistId("add_custom_impl") => Some("refactor.rewrite.add_custom_impl".to_string()),
708 _ => None,
709 };
710
711 Ok(CodeAction { 704 Ok(CodeAction {
712 title, 705 title,
713 kind, 706 kind: Some(String::new()),
714 diagnostics: None, 707 diagnostics: None,
715 edit: None, 708 edit: None,
716 command: Some(command), 709 command: Some(command),
@@ -812,6 +805,23 @@ pub fn handle_code_action(
812 } 805 }
813 } 806 }
814 807
808 // If the client only supports commands then filter the list
809 // and remove and actions that depend on edits.
810 if !world.config.client_caps.code_action_literals {
811 // FIXME: use drain_filter once it hits stable.
812 res = res
813 .into_iter()
814 .filter_map(|it| match it {
815 cmd @ lsp_types::CodeActionOrCommand::Command(_) => Some(cmd),
816 lsp_types::CodeActionOrCommand::CodeAction(action) => match action.command {
817 Some(cmd) if action.edit.is_none() => {
818 Some(lsp_types::CodeActionOrCommand::Command(cmd))
819 }
820 _ => None,
821 },
822 })
823 .collect();
824 }
815 Ok(Some(res)) 825 Ok(Some(res))
816} 826}
817 827
diff --git a/crates/rust-analyzer/tests/heavy_tests/support.rs b/crates/rust-analyzer/tests/heavy_tests/support.rs
index e4fe3411a..8d47ee4f6 100644
--- a/crates/rust-analyzer/tests/heavy_tests/support.rs
+++ b/crates/rust-analyzer/tests/heavy_tests/support.rs
@@ -77,7 +77,11 @@ impl<'a> Project<'a> {
77 let roots = self.roots.into_iter().map(|root| tmp_dir.path().join(root)).collect(); 77 let roots = self.roots.into_iter().map(|root| tmp_dir.path().join(root)).collect();
78 78
79 let mut config = Config { 79 let mut config = Config {
80 client_caps: ClientCapsConfig { location_link: true, ..Default::default() }, 80 client_caps: ClientCapsConfig {
81 location_link: true,
82 code_action_literals: true,
83 ..Default::default()
84 },
81 with_sysroot: self.with_sysroot, 85 with_sysroot: self.with_sysroot,
82 ..Config::default() 86 ..Config::default()
83 }; 87 };