aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r--crates/ra_ide/src/assists.rs42
-rw-r--r--crates/ra_ide/src/completion/completion_item.rs3
-rw-r--r--crates/ra_ide/src/hover.rs49
-rw-r--r--crates/ra_ide/src/lib.rs38
-rw-r--r--crates/ra_ide/src/source_change.rs121
-rw-r--r--crates/ra_ide/src/ssr.rs14
-rw-r--r--crates/ra_ide/src/typing.rs5
7 files changed, 84 insertions, 188 deletions
diff --git a/crates/ra_ide/src/assists.rs b/crates/ra_ide/src/assists.rs
deleted file mode 100644
index 389339a03..000000000
--- a/crates/ra_ide/src/assists.rs
+++ /dev/null
@@ -1,42 +0,0 @@
1//! FIXME: write short doc here
2
3use ra_assists::{resolved_assists, AssistAction};
4use ra_db::{FilePosition, FileRange};
5use ra_ide_db::RootDatabase;
6
7use crate::{FileId, SourceChange, SourceFileEdit};
8
9pub use ra_assists::AssistId;
10
11#[derive(Debug)]
12pub struct Assist {
13 pub id: AssistId,
14 pub label: String,
15 pub group_label: Option<String>,
16 pub source_change: SourceChange,
17}
18
19pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<Assist> {
20 resolved_assists(db, frange)
21 .into_iter()
22 .map(|assist| {
23 let file_id = frange.file_id;
24 Assist {
25 id: assist.label.id,
26 label: assist.label.label.clone(),
27 group_label: assist.label.group.map(|it| it.0),
28 source_change: action_to_edit(assist.action, file_id, assist.label.label.clone()),
29 }
30 })
31 .collect()
32}
33
34fn action_to_edit(action: AssistAction, file_id: FileId, label: String) -> SourceChange {
35 let file_id = match action.file {
36 ra_assists::AssistFile::TargetFile(it) => it,
37 _ => file_id,
38 };
39 let file_edit = SourceFileEdit { file_id, edit: action.edit };
40 SourceChange::source_file_edit(label, file_edit)
41 .with_cursor_opt(action.cursor_position.map(|offset| FilePosition { offset, file_id }))
42}
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs
index 383b23ac4..6021f7279 100644
--- a/crates/ra_ide/src/completion/completion_item.rs
+++ b/crates/ra_ide/src/completion/completion_item.rs
@@ -2,11 +2,12 @@
2 2
3use std::fmt; 3use std::fmt;
4 4
5use super::completion_config::SnippetCap;
6use hir::Documentation; 5use hir::Documentation;
7use ra_syntax::TextRange; 6use ra_syntax::TextRange;
8use ra_text_edit::TextEdit; 7use ra_text_edit::TextEdit;
9 8
9use crate::completion::completion_config::SnippetCap;
10
10/// `CompletionItem` describes a single completion variant in the editor pop-up. 11/// `CompletionItem` describes a single completion variant in the editor pop-up.
11/// It is basically a POD with various properties. To construct a 12/// It is basically a POD with various properties. To construct a
12/// `CompletionItem`, use `new` method and the `Builder` struct. 13/// `CompletionItem`, use `new` method and the `Builder` struct.
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 54d318858..06d4f1c63 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -143,7 +143,7 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
143 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), 143 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
144 ModuleDef::BuiltinType(it) => Some(it.to_string()), 144 ModuleDef::BuiltinType(it) => Some(it.to_string()),
145 }, 145 },
146 Definition::Local(it) => Some(rust_code_markup(&it.ty(db).display_truncated(db, None))), 146 Definition::Local(it) => Some(rust_code_markup(&it.ty(db).display(db))),
147 Definition::TypeParam(_) | Definition::SelfType(_) => { 147 Definition::TypeParam(_) | Definition::SelfType(_) => {
148 // FIXME: Hover for generic param 148 // FIXME: Hover for generic param
149 None 149 None
@@ -208,7 +208,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
208 } 208 }
209 }?; 209 }?;
210 210
211 res.extend(Some(rust_code_markup(&ty.display_truncated(db, None)))); 211 res.extend(Some(rust_code_markup(&ty.display(db))));
212 let range = sema.original_range(&node).range; 212 let range = sema.original_range(&node).range;
213 Some(RangeInfo::new(range, res)) 213 Some(RangeInfo::new(range, res))
214} 214}
@@ -280,6 +280,47 @@ mod tests {
280 } 280 }
281 281
282 #[test] 282 #[test]
283 fn hover_shows_long_type_of_an_expression() {
284 check_hover_result(
285 r#"
286 //- /main.rs
287 struct Scan<A, B, C> {
288 a: A,
289 b: B,
290 c: C,
291 }
292
293 struct FakeIter<I> {
294 inner: I,
295 }
296
297 struct OtherStruct<T> {
298 i: T,
299 }
300
301 enum FakeOption<T> {
302 Some(T),
303 None,
304 }
305
306 fn scan<A, B, C>(a: A, b: B, c: C) -> FakeIter<Scan<OtherStruct<A>, B, C>> {
307 FakeIter { inner: Scan { a, b, c } }
308 }
309
310 fn main() {
311 let num: i32 = 55;
312 let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> FakeOption<u32> {
313 FakeOption::Some(*memo + value)
314 };
315 let number = 5u32;
316 let mut iter<|> = scan(OtherStruct { i: num }, closure, number);
317 }
318 "#,
319 &["FakeIter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> FakeOption<u32>, u32>>"],
320 );
321 }
322
323 #[test]
283 fn hover_shows_fn_signature() { 324 fn hover_shows_fn_signature() {
284 // Single file with result 325 // Single file with result
285 check_hover_result( 326 check_hover_result(
@@ -405,7 +446,7 @@ mod tests {
405 } 446 }
406 447
407 #[test] 448 #[test]
408 fn hover_omits_default_generic_types() { 449 fn hover_default_generic_types() {
409 check_hover_result( 450 check_hover_result(
410 r#" 451 r#"
411//- /main.rs 452//- /main.rs
@@ -417,7 +458,7 @@ struct Test<K, T = u8> {
417fn main() { 458fn main() {
418 let zz<|> = Test { t: 23, k: 33 }; 459 let zz<|> = Test { t: 23, k: 33 };
419}"#, 460}"#,
420 &["Test<i32>"], 461 &["Test<i32, u8>"],
421 ); 462 );
422 } 463 }
423 464
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 09f602fe1..737f87109 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -16,7 +16,6 @@ macro_rules! eprintln {
16} 16}
17 17
18pub mod mock_analysis; 18pub mod mock_analysis;
19mod source_change;
20 19
21mod prime_caches; 20mod prime_caches;
22mod status; 21mod status;
@@ -32,7 +31,6 @@ mod syntax_highlighting;
32mod parent_module; 31mod parent_module;
33mod references; 32mod references;
34mod impls; 33mod impls;
35mod assists;
36mod diagnostics; 34mod diagnostics;
37mod syntax_tree; 35mod syntax_tree;
38mod folding_ranges; 36mod folding_ranges;
@@ -65,7 +63,6 @@ use ra_syntax::{SourceFile, TextRange, TextSize};
65use crate::display::ToNav; 63use crate::display::ToNav;
66 64
67pub use crate::{ 65pub use crate::{
68 assists::{Assist, AssistId},
69 call_hierarchy::CallItem, 66 call_hierarchy::CallItem,
70 completion::{ 67 completion::{
71 CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat, 68 CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat,
@@ -78,7 +75,6 @@ pub use crate::{
78 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, 75 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
79 references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult}, 76 references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult},
80 runnables::{Runnable, RunnableKind, TestId}, 77 runnables::{Runnable, RunnableKind, TestId},
81 source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
82 ssr::SsrError, 78 ssr::SsrError,
83 syntax_highlighting::{ 79 syntax_highlighting::{
84 Highlight, HighlightModifier, HighlightModifiers, HighlightTag, HighlightedRange, 80 Highlight, HighlightModifier, HighlightModifiers, HighlightTag, HighlightedRange,
@@ -86,6 +82,7 @@ pub use crate::{
86}; 82};
87 83
88pub use hir::Documentation; 84pub use hir::Documentation;
85pub use ra_assists::AssistId;
89pub use ra_db::{ 86pub use ra_db::{
90 Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId, 87 Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId,
91}; 88};
@@ -94,6 +91,7 @@ pub use ra_ide_db::{
94 line_index::{LineCol, LineIndex}, 91 line_index::{LineCol, LineIndex},
95 line_index_utils::translate_offset_with_edit, 92 line_index_utils::translate_offset_with_edit,
96 search::SearchScope, 93 search::SearchScope,
94 source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
97 symbol_index::Query, 95 symbol_index::Query,
98 RootDatabase, 96 RootDatabase,
99}; 97};
@@ -135,10 +133,12 @@ pub struct AnalysisHost {
135 db: RootDatabase, 133 db: RootDatabase,
136} 134}
137 135
138impl Default for AnalysisHost { 136#[derive(Debug)]
139 fn default() -> AnalysisHost { 137pub struct Assist {
140 AnalysisHost::new(None) 138 pub id: AssistId,
141 } 139 pub label: String,
140 pub group_label: Option<String>,
141 pub source_change: SourceChange,
142} 142}
143 143
144impl AnalysisHost { 144impl AnalysisHost {
@@ -188,6 +188,12 @@ impl AnalysisHost {
188 } 188 }
189} 189}
190 190
191impl Default for AnalysisHost {
192 fn default() -> AnalysisHost {
193 AnalysisHost::new(None)
194 }
195}
196
191/// Analysis is a snapshot of a world state at a moment in time. It is the main 197/// Analysis is a snapshot of a world state at a moment in time. It is the main
192/// entry point for asking semantic information about the world. When the world 198/// entry point for asking semantic information about the world. When the world
193/// state is advanced using `AnalysisHost::apply_change` method, all existing 199/// state is advanced using `AnalysisHost::apply_change` method, all existing
@@ -296,7 +302,7 @@ impl Analysis {
296 file_id: frange.file_id, 302 file_id: frange.file_id,
297 edit: join_lines::join_lines(&parse.tree(), frange.range), 303 edit: join_lines::join_lines(&parse.tree(), frange.range),
298 }; 304 };
299 SourceChange::source_file_edit("join lines", file_edit) 305 SourceChange::source_file_edit("Join lines", file_edit)
300 }) 306 })
301 } 307 }
302 308
@@ -465,7 +471,17 @@ impl Analysis {
465 /// Computes assists (aka code actions aka intentions) for the given 471 /// Computes assists (aka code actions aka intentions) for the given
466 /// position. 472 /// position.
467 pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<Assist>> { 473 pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<Assist>> {
468 self.with_db(|db| assists::assists(db, frange)) 474 self.with_db(|db| {
475 ra_assists::resolved_assists(db, frange)
476 .into_iter()
477 .map(|assist| Assist {
478 id: assist.label.id,
479 label: assist.label.label,
480 group_label: assist.label.group.map(|it| it.0),
481 source_change: assist.source_change,
482 })
483 .collect()
484 })
469 } 485 }
470 486
471 /// Computes the set of diagnostics for the given file. 487 /// Computes the set of diagnostics for the given file.
@@ -490,7 +506,7 @@ impl Analysis {
490 ) -> Cancelable<Result<SourceChange, SsrError>> { 506 ) -> Cancelable<Result<SourceChange, SsrError>> {
491 self.with_db(|db| { 507 self.with_db(|db| {
492 let edits = ssr::parse_search_replace(query, parse_only, db)?; 508 let edits = ssr::parse_search_replace(query, parse_only, db)?;
493 Ok(SourceChange::source_file_edits("ssr", edits)) 509 Ok(SourceChange::source_file_edits("Structural Search Replace", edits))
494 }) 510 })
495 } 511 }
496 512
diff --git a/crates/ra_ide/src/source_change.rs b/crates/ra_ide/src/source_change.rs
deleted file mode 100644
index 10afd7825..000000000
--- a/crates/ra_ide/src/source_change.rs
+++ /dev/null
@@ -1,121 +0,0 @@
1//! This modules defines type to represent changes to the source code, that flow
2//! from the server to the client.
3//!
4//! It can be viewed as a dual for `AnalysisChange`.
5
6use ra_db::RelativePathBuf;
7use ra_text_edit::TextEdit;
8
9use crate::{FileId, FilePosition, SourceRootId, TextSize};
10
11#[derive(Debug)]
12pub struct SourceChange {
13 pub label: String,
14 pub source_file_edits: Vec<SourceFileEdit>,
15 pub file_system_edits: Vec<FileSystemEdit>,
16 pub cursor_position: Option<FilePosition>,
17}
18
19impl SourceChange {
20 /// Creates a new SourceChange with the given label
21 /// from the edits.
22 pub(crate) fn from_edits<L: Into<String>>(
23 label: L,
24 source_file_edits: Vec<SourceFileEdit>,
25 file_system_edits: Vec<FileSystemEdit>,
26 ) -> Self {
27 SourceChange {
28 label: label.into(),
29 source_file_edits,
30 file_system_edits,
31 cursor_position: None,
32 }
33 }
34
35 /// Creates a new SourceChange with the given label,
36 /// containing only the given `SourceFileEdits`.
37 pub(crate) fn source_file_edits<L: Into<String>>(label: L, edits: Vec<SourceFileEdit>) -> Self {
38 let label = label.into();
39 assert!(label.starts_with(char::is_uppercase));
40 SourceChange {
41 label: label,
42 source_file_edits: edits,
43 file_system_edits: vec![],
44 cursor_position: None,
45 }
46 }
47
48 /// Creates a new SourceChange with the given label,
49 /// containing only the given `FileSystemEdits`.
50 pub(crate) fn file_system_edits<L: Into<String>>(label: L, edits: Vec<FileSystemEdit>) -> Self {
51 SourceChange {
52 label: label.into(),
53 source_file_edits: vec![],
54 file_system_edits: edits,
55 cursor_position: None,
56 }
57 }
58
59 /// Creates a new SourceChange with the given label,
60 /// containing only a single `SourceFileEdit`.
61 pub(crate) fn source_file_edit<L: Into<String>>(label: L, edit: SourceFileEdit) -> Self {
62 SourceChange::source_file_edits(label, vec![edit])
63 }
64
65 /// Creates a new SourceChange with the given label
66 /// from the given `FileId` and `TextEdit`
67 pub(crate) fn source_file_edit_from<L: Into<String>>(
68 label: L,
69 file_id: FileId,
70 edit: TextEdit,
71 ) -> Self {
72 SourceChange::source_file_edit(label, SourceFileEdit { file_id, edit })
73 }
74
75 /// Creates a new SourceChange with the given label
76 /// from the given `FileId` and `TextEdit`
77 pub(crate) fn file_system_edit<L: Into<String>>(label: L, edit: FileSystemEdit) -> Self {
78 SourceChange::file_system_edits(label, vec![edit])
79 }
80
81 /// Sets the cursor position to the given `FilePosition`
82 pub(crate) fn with_cursor(mut self, cursor_position: FilePosition) -> Self {
83 self.cursor_position = Some(cursor_position);
84 self
85 }
86
87 /// Sets the cursor position to the given `FilePosition`
88 pub(crate) fn with_cursor_opt(mut self, cursor_position: Option<FilePosition>) -> Self {
89 self.cursor_position = cursor_position;
90 self
91 }
92}
93
94#[derive(Debug)]
95pub struct SourceFileEdit {
96 pub file_id: FileId,
97 pub edit: TextEdit,
98}
99
100#[derive(Debug)]
101pub enum FileSystemEdit {
102 CreateFile { source_root: SourceRootId, path: RelativePathBuf },
103 MoveFile { src: FileId, dst_source_root: SourceRootId, dst_path: RelativePathBuf },
104}
105
106pub(crate) struct SingleFileChange {
107 pub label: String,
108 pub edit: TextEdit,
109 pub cursor_position: Option<TextSize>,
110}
111
112impl SingleFileChange {
113 pub(crate) fn into_source_change(self, file_id: FileId) -> SourceChange {
114 SourceChange {
115 label: self.label,
116 source_file_edits: vec![SourceFileEdit { file_id, edit: self.edit }],
117 file_system_edits: Vec::new(),
118 cursor_position: self.cursor_position.map(|offset| FilePosition { file_id, offset }),
119 }
120 }
121}
diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs
index 8bf52d0fa..1873d1d0d 100644
--- a/crates/ra_ide/src/ssr.rs
+++ b/crates/ra_ide/src/ssr.rs
@@ -1,18 +1,18 @@
1//! structural search replace 1//! structural search replace
2 2
3use crate::source_change::SourceFileEdit; 3use std::{collections::HashMap, iter::once, str::FromStr};
4
4use ra_db::{SourceDatabase, SourceDatabaseExt}; 5use ra_db::{SourceDatabase, SourceDatabaseExt};
5use ra_ide_db::symbol_index::SymbolsDatabase; 6use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase};
6use ra_ide_db::RootDatabase;
7use ra_syntax::ast::make::try_expr_from_text;
8use ra_syntax::ast::{ 7use ra_syntax::ast::{
9 ArgList, AstToken, CallExpr, Comment, Expr, MethodCallExpr, RecordField, RecordLit, 8 make::try_expr_from_text, ArgList, AstToken, CallExpr, Comment, Expr, MethodCallExpr,
9 RecordField, RecordLit,
10}; 10};
11use ra_syntax::{AstNode, SyntaxElement, SyntaxKind, SyntaxNode}; 11use ra_syntax::{AstNode, SyntaxElement, SyntaxKind, SyntaxNode};
12use ra_text_edit::{TextEdit, TextEditBuilder}; 12use ra_text_edit::{TextEdit, TextEditBuilder};
13use rustc_hash::FxHashMap; 13use rustc_hash::FxHashMap;
14use std::collections::HashMap; 14
15use std::{iter::once, str::FromStr}; 15use crate::SourceFileEdit;
16 16
17#[derive(Debug, PartialEq)] 17#[derive(Debug, PartialEq)]
18pub struct SsrError(String); 18pub struct SsrError(String);
diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs
index a03da4693..6f04f0be4 100644
--- a/crates/ra_ide/src/typing.rs
+++ b/crates/ra_ide/src/typing.rs
@@ -17,15 +17,16 @@ mod on_enter;
17 17
18use ra_db::{FilePosition, SourceDatabase}; 18use ra_db::{FilePosition, SourceDatabase};
19use ra_fmt::leading_indent; 19use ra_fmt::leading_indent;
20use ra_ide_db::RootDatabase; 20use ra_ide_db::{source_change::SingleFileChange, RootDatabase};
21use ra_syntax::{ 21use ra_syntax::{
22 algo::find_node_at_offset, 22 algo::find_node_at_offset,
23 ast::{self, AstToken}, 23 ast::{self, AstToken},
24 AstNode, SourceFile, TextRange, TextSize, 24 AstNode, SourceFile, TextRange, TextSize,
25}; 25};
26
26use ra_text_edit::TextEdit; 27use ra_text_edit::TextEdit;
27 28
28use crate::{source_change::SingleFileChange, SourceChange}; 29use crate::SourceChange;
29 30
30pub(crate) use on_enter::on_enter; 31pub(crate) use on_enter::on_enter;
31 32