aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ide_assists/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/from_proto.rs30
-rw-r--r--crates/rust-analyzer/src/handlers.rs100
-rw-r--r--crates/rust-analyzer/src/to_proto.rs39
-rw-r--r--crates/rust-analyzer/tests/rust-analyzer/main.rs2
5 files changed, 72 insertions, 101 deletions
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index 3e2c82dac..3694f468f 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -28,7 +28,9 @@ pub use assist_config::AssistConfig;
28 28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)] 29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum AssistKind { 30pub enum AssistKind {
31 // FIXME: does the None variant make sense? Probably not.
31 None, 32 None,
33
32 QuickFix, 34 QuickFix,
33 Generate, 35 Generate,
34 Refactor, 36 Refactor,
diff --git a/crates/rust-analyzer/src/from_proto.rs b/crates/rust-analyzer/src/from_proto.rs
index 5b02b2598..712d5a9c2 100644
--- a/crates/rust-analyzer/src/from_proto.rs
+++ b/crates/rust-analyzer/src/from_proto.rs
@@ -42,27 +42,27 @@ pub(crate) fn text_range(line_index: &LineIndex, range: lsp_types::Range) -> Tex
42 TextRange::new(start, end) 42 TextRange::new(start, end)
43} 43}
44 44
45pub(crate) fn file_id(world: &GlobalStateSnapshot, url: &lsp_types::Url) -> Result<FileId> { 45pub(crate) fn file_id(snap: &GlobalStateSnapshot, url: &lsp_types::Url) -> Result<FileId> {
46 world.url_to_file_id(url) 46 snap.url_to_file_id(url)
47} 47}
48 48
49pub(crate) fn file_position( 49pub(crate) fn file_position(
50 world: &GlobalStateSnapshot, 50 snap: &GlobalStateSnapshot,
51 tdpp: lsp_types::TextDocumentPositionParams, 51 tdpp: lsp_types::TextDocumentPositionParams,
52) -> Result<FilePosition> { 52) -> Result<FilePosition> {
53 let file_id = file_id(world, &tdpp.text_document.uri)?; 53 let file_id = file_id(snap, &tdpp.text_document.uri)?;
54 let line_index = world.file_line_index(file_id)?; 54 let line_index = snap.file_line_index(file_id)?;
55 let offset = offset(&line_index, tdpp.position); 55 let offset = offset(&line_index, tdpp.position);
56 Ok(FilePosition { file_id, offset }) 56 Ok(FilePosition { file_id, offset })
57} 57}
58 58
59pub(crate) fn file_range( 59pub(crate) fn file_range(
60 world: &GlobalStateSnapshot, 60 snap: &GlobalStateSnapshot,
61 text_document_identifier: lsp_types::TextDocumentIdentifier, 61 text_document_identifier: lsp_types::TextDocumentIdentifier,
62 range: lsp_types::Range, 62 range: lsp_types::Range,
63) -> Result<FileRange> { 63) -> Result<FileRange> {
64 let file_id = file_id(world, &text_document_identifier.uri)?; 64 let file_id = file_id(snap, &text_document_identifier.uri)?;
65 let line_index = world.file_line_index(file_id)?; 65 let line_index = snap.file_line_index(file_id)?;
66 let range = text_range(&line_index, range); 66 let range = text_range(&line_index, range);
67 Ok(FileRange { file_id, range }) 67 Ok(FileRange { file_id, range })
68} 68}
@@ -82,7 +82,7 @@ pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option<AssistKind>
82} 82}
83 83
84pub(crate) fn annotation( 84pub(crate) fn annotation(
85 world: &GlobalStateSnapshot, 85 snap: &GlobalStateSnapshot,
86 code_lens: lsp_types::CodeLens, 86 code_lens: lsp_types::CodeLens,
87) -> Result<Annotation> { 87) -> Result<Annotation> {
88 let data = code_lens.data.unwrap(); 88 let data = code_lens.data.unwrap();
@@ -91,25 +91,25 @@ pub(crate) fn annotation(
91 match resolve { 91 match resolve {
92 lsp_ext::CodeLensResolveData::Impls(params) => { 92 lsp_ext::CodeLensResolveData::Impls(params) => {
93 let file_id = 93 let file_id =
94 world.url_to_file_id(&params.text_document_position_params.text_document.uri)?; 94 snap.url_to_file_id(&params.text_document_position_params.text_document.uri)?;
95 let line_index = world.file_line_index(file_id)?; 95 let line_index = snap.file_line_index(file_id)?;
96 96
97 Ok(Annotation { 97 Ok(Annotation {
98 range: text_range(&line_index, code_lens.range), 98 range: text_range(&line_index, code_lens.range),
99 kind: AnnotationKind::HasImpls { 99 kind: AnnotationKind::HasImpls {
100 position: file_position(world, params.text_document_position_params)?, 100 position: file_position(snap, params.text_document_position_params)?,
101 data: None, 101 data: None,
102 }, 102 },
103 }) 103 })
104 } 104 }
105 lsp_ext::CodeLensResolveData::References(params) => { 105 lsp_ext::CodeLensResolveData::References(params) => {
106 let file_id = world.url_to_file_id(&params.text_document.uri)?; 106 let file_id = snap.url_to_file_id(&params.text_document.uri)?;
107 let line_index = world.file_line_index(file_id)?; 107 let line_index = snap.file_line_index(file_id)?;
108 108
109 Ok(Annotation { 109 Ok(Annotation {
110 range: text_range(&line_index, code_lens.range), 110 range: text_range(&line_index, code_lens.range),
111 kind: AnnotationKind::HasReferences { 111 kind: AnnotationKind::HasReferences {
112 position: file_position(world, params)?, 112 position: file_position(snap, params)?,
113 data: None, 113 data: None,
114 }, 114 },
115 }) 115 })
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 107685c63..85c70373a 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -8,8 +8,8 @@ use std::{
8}; 8};
9 9
10use ide::{ 10use ide::{
11 AnnotationConfig, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, Query, 11 AnnotationConfig, AssistKind, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData,
12 RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange, TextEdit, 12 Query, RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange, TextEdit,
13}; 13};
14use ide_db::SymbolKind; 14use ide_db::SymbolKind;
15use itertools::Itertools; 15use itertools::Itertools;
@@ -17,7 +17,7 @@ use lsp_server::ErrorCode;
17use lsp_types::{ 17use lsp_types::{
18 CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, 18 CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
19 CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, 19 CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams,
20 CodeActionKind, CodeLens, CompletionItem, Diagnostic, DiagnosticTag, DocumentFormattingParams, 20 CodeLens, CompletionItem, Diagnostic, DiagnosticTag, DocumentFormattingParams,
21 DocumentHighlight, FoldingRange, FoldingRangeParams, HoverContents, Location, NumberOrString, 21 DocumentHighlight, FoldingRange, FoldingRangeParams, HoverContents, Location, NumberOrString,
22 Position, PrepareRenameResponse, Range, RenameParams, SemanticTokensDeltaParams, 22 Position, PrepareRenameResponse, Range, RenameParams, SemanticTokensDeltaParams,
23 SemanticTokensFullDeltaResult, SemanticTokensParams, SemanticTokensRangeParams, 23 SemanticTokensFullDeltaResult, SemanticTokensParams, SemanticTokensRangeParams,
@@ -36,7 +36,7 @@ use crate::{
36 diff::diff, 36 diff::diff,
37 from_proto, 37 from_proto,
38 global_state::{GlobalState, GlobalStateSnapshot}, 38 global_state::{GlobalState, GlobalStateSnapshot},
39 line_index::{LineEndings, LineIndex}, 39 line_index::LineEndings,
40 lsp_ext::{self, InlayHint, InlayHintsParams}, 40 lsp_ext::{self, InlayHint, InlayHintsParams},
41 lsp_utils::all_edits_are_disjoint, 41 lsp_utils::all_edits_are_disjoint,
42 to_proto, LspError, Result, 42 to_proto, LspError, Result,
@@ -982,86 +982,66 @@ pub(crate) fn handle_code_action(
982 params: lsp_types::CodeActionParams, 982 params: lsp_types::CodeActionParams,
983) -> Result<Option<Vec<lsp_ext::CodeAction>>> { 983) -> Result<Option<Vec<lsp_ext::CodeAction>>> {
984 let _p = profile::span("handle_code_action"); 984 let _p = profile::span("handle_code_action");
985 // We intentionally don't support command-based actions, as those either 985
986 // requires custom client-code anyway, or requires server-initiated edits.
987 // Server initiated edits break causality, so we avoid those as well.
988 if !snap.config.code_action_literals() { 986 if !snap.config.code_action_literals() {
987 // We intentionally don't support command-based actions, as those either
988 // require either custom client-code or server-initiated edits. Server
989 // initiated edits break causality, so we avoid those.
989 return Ok(None); 990 return Ok(None);
990 } 991 }
991 992
992 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?; 993 let line_index =
993 let line_index = snap.file_line_index(file_id)?; 994 snap.file_line_index(from_proto::file_id(&snap, &params.text_document.uri)?)?;
994 let range = from_proto::text_range(&line_index, params.range); 995 let frange = from_proto::file_range(&snap, params.text_document.clone(), params.range)?;
995 let frange = FileRange { file_id, range };
996 996
997 let mut assists_config = snap.config.assist(); 997 let mut assists_config = snap.config.assist();
998 assists_config.allowed = params 998 assists_config.allowed = params
999 .clone()
1000 .context 999 .context
1001 .only 1000 .only
1001 .clone()
1002 .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); 1002 .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
1003 1003
1004 let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); 1004 let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
1005 1005
1006 let include_quick_fixes = match &params.context.only { 1006 let include_quick_fixes = match &assists_config.allowed {
1007 Some(v) => v.iter().any(|it| { 1007 Some(v) => v.iter().any(|it| it == &AssistKind::None || it == &AssistKind::QuickFix),
1008 it == &lsp_types::CodeActionKind::EMPTY || it == &lsp_types::CodeActionKind::QUICKFIX
1009 }),
1010 None => true, 1008 None => true,
1011 }; 1009 };
1012 if include_quick_fixes { 1010 let code_action_resolve_cap = snap.config.code_action_resolve();
1013 add_quick_fixes(&snap, frange, &line_index, &mut res)?;
1014 }
1015
1016 if snap.config.code_action_resolve() {
1017 for (index, assist) in
1018 snap.analysis.assists(&assists_config, false, frange)?.into_iter().enumerate()
1019 {
1020 res.push(to_proto::unresolved_code_action(&snap, params.clone(), assist, index)?);
1021 }
1022 } else {
1023 for assist in snap.analysis.assists(&assists_config, true, frange)?.into_iter() {
1024 res.push(to_proto::resolved_code_action(&snap, assist)?);
1025 }
1026 }
1027 1011
1028 Ok(Some(res)) 1012 let mut assists = Vec::new();
1029}
1030 1013
1031fn add_quick_fixes( 1014 // Fixes from native diagnostics.
1032 snap: &GlobalStateSnapshot, 1015 if include_quick_fixes {
1033 frange: FileRange, 1016 let diagnostics = snap.analysis.diagnostics(&snap.config.diagnostics(), frange.file_id)?;
1034 line_index: &LineIndex, 1017 assists.extend(
1035 acc: &mut Vec<lsp_ext::CodeAction>, 1018 diagnostics
1036) -> Result<()> { 1019 .into_iter()
1037 let diagnostics = snap.analysis.diagnostics(&snap.config.diagnostics(), frange.file_id)?; 1020 .filter_map(|d| d.fix)
1021 .filter(|fix| fix.target.intersect(frange.range).is_some()),
1022 )
1023 }
1038 1024
1039 for fix in diagnostics 1025 // Assists proper.
1040 .into_iter() 1026 assists.extend(snap.analysis.assists(&assists_config, !code_action_resolve_cap, frange)?);
1041 .filter_map(|d| d.fix) 1027 for (index, assist) in assists.into_iter().enumerate() {
1042 .filter(|fix| fix.target.intersect(frange.range).is_some()) 1028 let resolve_data =
1043 { 1029 if code_action_resolve_cap { Some((index, params.clone())) } else { None };
1044 if let Some(source_change) = fix.source_change { 1030 let code_action = to_proto::code_action(&snap, assist, resolve_data)?;
1045 let edit = to_proto::snippet_workspace_edit(&snap, source_change)?; 1031 res.push(code_action)
1046 let action = lsp_ext::CodeAction {
1047 title: fix.label.to_string(),
1048 group: None,
1049 kind: Some(CodeActionKind::QUICKFIX),
1050 edit: Some(edit),
1051 is_preferred: Some(false),
1052 data: None,
1053 };
1054 acc.push(action);
1055 }
1056 } 1032 }
1057 1033
1034 // Fixes from `cargo check`.
1058 for fix in snap.check_fixes.get(&frange.file_id).into_iter().flatten() { 1035 for fix in snap.check_fixes.get(&frange.file_id).into_iter().flatten() {
1036 // FIXME: this mapping is awkward and shouldn't exist. Refactor
1037 // `snap.check_fixes` to not convert to LSP prematurely.
1059 let fix_range = from_proto::text_range(&line_index, fix.range); 1038 let fix_range = from_proto::text_range(&line_index, fix.range);
1060 if fix_range.intersect(frange.range).is_some() { 1039 if fix_range.intersect(frange.range).is_some() {
1061 acc.push(fix.action.clone()); 1040 res.push(fix.action.clone());
1062 } 1041 }
1063 } 1042 }
1064 Ok(()) 1043
1044 Ok(Some(res))
1065} 1045}
1066 1046
1067pub(crate) fn handle_code_action_resolve( 1047pub(crate) fn handle_code_action_resolve(
@@ -1091,7 +1071,7 @@ pub(crate) fn handle_code_action_resolve(
1091 let index = index.parse::<usize>().unwrap(); 1071 let index = index.parse::<usize>().unwrap();
1092 let assist = &assists[index]; 1072 let assist = &assists[index];
1093 assert!(assist.id.0 == id); 1073 assert!(assist.id.0 == id);
1094 let edit = to_proto::resolved_code_action(&snap, assist.clone())?.edit; 1074 let edit = to_proto::code_action(&snap, assist.clone(), None)?.edit;
1095 code_action.edit = edit; 1075 code_action.edit = edit;
1096 Ok(code_action) 1076 Ok(code_action)
1097} 1077}
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 9fac562ff..53852bfdc 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -843,40 +843,31 @@ pub(crate) fn code_action_kind(kind: AssistKind) -> lsp_types::CodeActionKind {
843 } 843 }
844} 844}
845 845
846pub(crate) fn unresolved_code_action( 846pub(crate) fn code_action(
847 snap: &GlobalStateSnapshot, 847 snap: &GlobalStateSnapshot,
848 code_action_params: lsp_types::CodeActionParams,
849 assist: Assist, 848 assist: Assist,
850 index: usize, 849 resolve_data: Option<(usize, lsp_types::CodeActionParams)>,
851) -> Result<lsp_ext::CodeAction> { 850) -> Result<lsp_ext::CodeAction> {
852 assert!(assist.source_change.is_none()); 851 let mut res = lsp_ext::CodeAction {
853 let res = lsp_ext::CodeAction {
854 title: assist.label.to_string(), 852 title: assist.label.to_string(),
855 group: assist.group.filter(|_| snap.config.code_action_group()).map(|gr| gr.0), 853 group: assist.group.filter(|_| snap.config.code_action_group()).map(|gr| gr.0),
856 kind: Some(code_action_kind(assist.id.1)), 854 kind: Some(code_action_kind(assist.id.1)),
857 edit: None, 855 edit: None,
858 is_preferred: None, 856 is_preferred: None,
859 data: Some(lsp_ext::CodeActionData {
860 id: format!("{}:{}", assist.id.0, index.to_string()),
861 code_action_params,
862 }),
863 };
864 Ok(res)
865}
866
867pub(crate) fn resolved_code_action(
868 snap: &GlobalStateSnapshot,
869 assist: Assist,
870) -> Result<lsp_ext::CodeAction> {
871 let change = assist.source_change.unwrap();
872 let res = lsp_ext::CodeAction {
873 edit: Some(snippet_workspace_edit(snap, change)?),
874 title: assist.label.to_string(),
875 group: assist.group.filter(|_| snap.config.code_action_group()).map(|gr| gr.0),
876 kind: Some(code_action_kind(assist.id.1)),
877 is_preferred: None,
878 data: None, 857 data: None,
879 }; 858 };
859 match (assist.source_change, resolve_data) {
860 (Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?),
861 (None, Some((index, code_action_params))) => {
862 res.data = Some(lsp_ext::CodeActionData {
863 id: format!("{}:{}", assist.id.0, index.to_string()),
864 code_action_params,
865 });
866 }
867 (None, None) => {
868 stdx::never!("assist should always be resolved if client can't do lazy resolving")
869 }
870 };
880 Ok(res) 871 Ok(res)
881} 872}
882 873
diff --git a/crates/rust-analyzer/tests/rust-analyzer/main.rs b/crates/rust-analyzer/tests/rust-analyzer/main.rs
index 1e4c04bbf..52a2674d5 100644
--- a/crates/rust-analyzer/tests/rust-analyzer/main.rs
+++ b/crates/rust-analyzer/tests/rust-analyzer/main.rs
@@ -340,7 +340,6 @@ fn main() {}
340 } 340 }
341 ] 341 ]
342 }, 342 },
343 "isPreferred": false,
344 "kind": "quickfix", 343 "kind": "quickfix",
345 "title": "Create module" 344 "title": "Create module"
346 }]), 345 }]),
@@ -411,7 +410,6 @@ fn main() {{}}
411 } 410 }
412 ] 411 ]
413 }, 412 },
414 "isPreferred": false,
415 "kind": "quickfix", 413 "kind": "quickfix",
416 "title": "Create module" 414 "title": "Create module"
417 }]), 415 }]),