aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ide_assists/src/lib.rs131
-rw-r--r--crates/ide_db/src/assists.rs136
-rw-r--r--crates/ide_db/src/lib.rs1
-rw-r--r--crates/ide_diagnostics/Cargo.toml1
-rw-r--r--crates/ide_diagnostics/src/incorrect_case.rs3
-rw-r--r--crates/ide_diagnostics/src/lib.rs5
-rw-r--r--crates/ide_diagnostics/src/missing_fields.rs3
-rw-r--r--crates/ide_diagnostics/src/missing_ok_or_some_in_tail_expr.rs3
-rw-r--r--crates/ide_diagnostics/src/unresolved_module.rs3
9 files changed, 147 insertions, 139 deletions
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index 804918284..fa378a622 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -17,139 +17,16 @@ mod tests;
17pub mod utils; 17pub mod utils;
18pub mod path_transform; 18pub mod path_transform;
19 19
20use std::str::FromStr;
21
22use hir::Semantics; 20use hir::Semantics;
23use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, RootDatabase}; 21use ide_db::{base_db::FileRange, RootDatabase};
24use syntax::TextRange; 22use syntax::TextRange;
25 23
26pub(crate) use crate::assist_context::{AssistContext, Assists}; 24pub(crate) use crate::assist_context::{AssistContext, Assists};
27 25
28pub use assist_config::AssistConfig; 26pub use assist_config::AssistConfig;
29 27pub use ide_db::assists::{
30#[derive(Debug, Clone, Copy, PartialEq, Eq)] 28 Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel, SingleResolve,
31pub enum AssistKind { 29};
32 // FIXME: does the None variant make sense? Probably not.
33 None,
34
35 QuickFix,
36 Generate,
37 Refactor,
38 RefactorExtract,
39 RefactorInline,
40 RefactorRewrite,
41}
42
43impl AssistKind {
44 pub fn contains(self, other: AssistKind) -> bool {
45 if self == other {
46 return true;
47 }
48
49 match self {
50 AssistKind::None | AssistKind::Generate => true,
51 AssistKind::Refactor => match other {
52 AssistKind::RefactorExtract
53 | AssistKind::RefactorInline
54 | AssistKind::RefactorRewrite => true,
55 _ => false,
56 },
57 _ => false,
58 }
59 }
60
61 pub fn name(&self) -> &str {
62 match self {
63 AssistKind::None => "None",
64 AssistKind::QuickFix => "QuickFix",
65 AssistKind::Generate => "Generate",
66 AssistKind::Refactor => "Refactor",
67 AssistKind::RefactorExtract => "RefactorExtract",
68 AssistKind::RefactorInline => "RefactorInline",
69 AssistKind::RefactorRewrite => "RefactorRewrite",
70 }
71 }
72}
73
74impl FromStr for AssistKind {
75 type Err = String;
76
77 fn from_str(s: &str) -> Result<Self, Self::Err> {
78 match s {
79 "None" => Ok(AssistKind::None),
80 "QuickFix" => Ok(AssistKind::QuickFix),
81 "Generate" => Ok(AssistKind::Generate),
82 "Refactor" => Ok(AssistKind::Refactor),
83 "RefactorExtract" => Ok(AssistKind::RefactorExtract),
84 "RefactorInline" => Ok(AssistKind::RefactorInline),
85 "RefactorRewrite" => Ok(AssistKind::RefactorRewrite),
86 unknown => Err(format!("Unknown AssistKind: '{}'", unknown)),
87 }
88 }
89}
90
91/// Unique identifier of the assist, should not be shown to the user
92/// directly.
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub struct AssistId(pub &'static str, pub AssistKind);
95
96/// A way to control how many asssist to resolve during the assist resolution.
97/// When an assist is resolved, its edits are calculated that might be costly to always do by default.
98#[derive(Debug)]
99pub enum AssistResolveStrategy {
100 /// No assists should be resolved.
101 None,
102 /// All assists should be resolved.
103 All,
104 /// Only a certain assist should be resolved.
105 Single(SingleResolve),
106}
107
108/// Hold the [`AssistId`] data of a certain assist to resolve.
109/// The original id object cannot be used due to a `'static` lifetime
110/// and the requirement to construct this struct dynamically during the resolve handling.
111#[derive(Debug)]
112pub struct SingleResolve {
113 /// The id of the assist.
114 pub assist_id: String,
115 // The kind of the assist.
116 pub assist_kind: AssistKind,
117}
118
119impl AssistResolveStrategy {
120 pub fn should_resolve(&self, id: &AssistId) -> bool {
121 match self {
122 AssistResolveStrategy::None => false,
123 AssistResolveStrategy::All => true,
124 AssistResolveStrategy::Single(single_resolve) => {
125 single_resolve.assist_id == id.0 && single_resolve.assist_kind == id.1
126 }
127 }
128 }
129}
130
131#[derive(Clone, Debug)]
132pub struct GroupLabel(pub String);
133
134#[derive(Debug, Clone)]
135pub struct Assist {
136 pub id: AssistId,
137 /// Short description of the assist, as shown in the UI.
138 pub label: Label,
139 pub group: Option<GroupLabel>,
140 /// Target ranges are used to sort assists: the smaller the target range,
141 /// the more specific assist is, and so it should be sorted first.
142 pub target: TextRange,
143 /// Computing source change sometimes is much more costly then computing the
144 /// other fields. Additionally, the actual change is not required to show
145 /// the lightbulb UI, it only is needed when the user tries to apply an
146 /// assist. So, we compute it lazily: the API allow requesting assists with
147 /// or without source change. We could (and in fact, used to) distinguish
148 /// between resolved and unresolved assists at the type level, but this is
149 /// cumbersome, especially if you want to embed an assist into another data
150 /// structure, such as a diagnostic.
151 pub source_change: Option<SourceChange>,
152}
153 30
154/// Return all the assists applicable at the given position. 31/// Return all the assists applicable at the given position.
155pub fn assists( 32pub fn assists(
diff --git a/crates/ide_db/src/assists.rs b/crates/ide_db/src/assists.rs
new file mode 100644
index 000000000..7881d8369
--- /dev/null
+++ b/crates/ide_db/src/assists.rs
@@ -0,0 +1,136 @@
1//! This module defines the `Assist` data structure. The actual assist live in
2//! the `ide_assists` downstream crate. We want to define the data structures in
3//! this low-level crate though, because `ide_diagnostics` also need them
4//! (fixits for diagnostics and assists are the same thing under the hood). We
5//! want to compile `ide_assists` and `ide_diagnostics` in parallel though, so
6//! we pull the common definitions upstream, to this crate.
7
8use std::str::FromStr;
9
10use syntax::TextRange;
11
12use crate::{label::Label, source_change::SourceChange};
13
14#[derive(Debug, Clone)]
15pub struct Assist {
16 pub id: AssistId,
17 /// Short description of the assist, as shown in the UI.
18 pub label: Label,
19 pub group: Option<GroupLabel>,
20 /// Target ranges are used to sort assists: the smaller the target range,
21 /// the more specific assist is, and so it should be sorted first.
22 pub target: TextRange,
23 /// Computing source change sometimes is much more costly then computing the
24 /// other fields. Additionally, the actual change is not required to show
25 /// the lightbulb UI, it only is needed when the user tries to apply an
26 /// assist. So, we compute it lazily: the API allow requesting assists with
27 /// or without source change. We could (and in fact, used to) distinguish
28 /// between resolved and unresolved assists at the type level, but this is
29 /// cumbersome, especially if you want to embed an assist into another data
30 /// structure, such as a diagnostic.
31 pub source_change: Option<SourceChange>,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum AssistKind {
36 // FIXME: does the None variant make sense? Probably not.
37 None,
38
39 QuickFix,
40 Generate,
41 Refactor,
42 RefactorExtract,
43 RefactorInline,
44 RefactorRewrite,
45}
46
47impl AssistKind {
48 pub fn contains(self, other: AssistKind) -> bool {
49 if self == other {
50 return true;
51 }
52
53 match self {
54 AssistKind::None | AssistKind::Generate => true,
55 AssistKind::Refactor => match other {
56 AssistKind::RefactorExtract
57 | AssistKind::RefactorInline
58 | AssistKind::RefactorRewrite => true,
59 _ => false,
60 },
61 _ => false,
62 }
63 }
64
65 pub fn name(&self) -> &str {
66 match self {
67 AssistKind::None => "None",
68 AssistKind::QuickFix => "QuickFix",
69 AssistKind::Generate => "Generate",
70 AssistKind::Refactor => "Refactor",
71 AssistKind::RefactorExtract => "RefactorExtract",
72 AssistKind::RefactorInline => "RefactorInline",
73 AssistKind::RefactorRewrite => "RefactorRewrite",
74 }
75 }
76}
77
78impl FromStr for AssistKind {
79 type Err = String;
80
81 fn from_str(s: &str) -> Result<Self, Self::Err> {
82 match s {
83 "None" => Ok(AssistKind::None),
84 "QuickFix" => Ok(AssistKind::QuickFix),
85 "Generate" => Ok(AssistKind::Generate),
86 "Refactor" => Ok(AssistKind::Refactor),
87 "RefactorExtract" => Ok(AssistKind::RefactorExtract),
88 "RefactorInline" => Ok(AssistKind::RefactorInline),
89 "RefactorRewrite" => Ok(AssistKind::RefactorRewrite),
90 unknown => Err(format!("Unknown AssistKind: '{}'", unknown)),
91 }
92 }
93}
94
95/// Unique identifier of the assist, should not be shown to the user
96/// directly.
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub struct AssistId(pub &'static str, pub AssistKind);
99
100/// A way to control how many asssist to resolve during the assist resolution.
101/// When an assist is resolved, its edits are calculated that might be costly to always do by default.
102#[derive(Debug)]
103pub enum AssistResolveStrategy {
104 /// No assists should be resolved.
105 None,
106 /// All assists should be resolved.
107 All,
108 /// Only a certain assist should be resolved.
109 Single(SingleResolve),
110}
111
112/// Hold the [`AssistId`] data of a certain assist to resolve.
113/// The original id object cannot be used due to a `'static` lifetime
114/// and the requirement to construct this struct dynamically during the resolve handling.
115#[derive(Debug)]
116pub struct SingleResolve {
117 /// The id of the assist.
118 pub assist_id: String,
119 // The kind of the assist.
120 pub assist_kind: AssistKind,
121}
122
123impl AssistResolveStrategy {
124 pub fn should_resolve(&self, id: &AssistId) -> bool {
125 match self {
126 AssistResolveStrategy::None => false,
127 AssistResolveStrategy::All => true,
128 AssistResolveStrategy::Single(single_resolve) => {
129 single_resolve.assist_id == id.0 && single_resolve.assist_kind == id.1
130 }
131 }
132 }
133}
134
135#[derive(Clone, Debug)]
136pub struct GroupLabel(pub String);
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs
index 105607dca..2ac215c06 100644
--- a/crates/ide_db/src/lib.rs
+++ b/crates/ide_db/src/lib.rs
@@ -3,6 +3,7 @@
3//! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search. 3//! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search.
4 4
5mod apply_change; 5mod apply_change;
6pub mod assists;
6pub mod label; 7pub mod label;
7pub mod line_index; 8pub mod line_index;
8pub mod symbol_index; 9pub mod symbol_index;
diff --git a/crates/ide_diagnostics/Cargo.toml b/crates/ide_diagnostics/Cargo.toml
index 738fca14e..fa2adf212 100644
--- a/crates/ide_diagnostics/Cargo.toml
+++ b/crates/ide_diagnostics/Cargo.toml
@@ -22,7 +22,6 @@ text_edit = { path = "../text_edit", version = "0.0.0" }
22cfg = { path = "../cfg", version = "0.0.0" } 22cfg = { path = "../cfg", version = "0.0.0" }
23hir = { path = "../hir", version = "0.0.0" } 23hir = { path = "../hir", version = "0.0.0" }
24ide_db = { path = "../ide_db", version = "0.0.0" } 24ide_db = { path = "../ide_db", version = "0.0.0" }
25ide_assists = { path = "../ide_assists", version = "0.0.0" }
26 25
27[dev-dependencies] 26[dev-dependencies]
28expect-test = "1.1" 27expect-test = "1.1"
diff --git a/crates/ide_diagnostics/src/incorrect_case.rs b/crates/ide_diagnostics/src/incorrect_case.rs
index 04fc779ce..8e1a93aa7 100644
--- a/crates/ide_diagnostics/src/incorrect_case.rs
+++ b/crates/ide_diagnostics/src/incorrect_case.rs
@@ -1,6 +1,5 @@
1use hir::{db::AstDatabase, InFile}; 1use hir::{db::AstDatabase, InFile};
2use ide_assists::Assist; 2use ide_db::{assists::Assist, base_db::FilePosition};
3use ide_db::base_db::FilePosition;
4use syntax::AstNode; 3use syntax::AstNode;
5 4
6use crate::{ 5use crate::{
diff --git a/crates/ide_diagnostics/src/lib.rs b/crates/ide_diagnostics/src/lib.rs
index 0d98307a2..2a16c73a8 100644
--- a/crates/ide_diagnostics/src/lib.rs
+++ b/crates/ide_diagnostics/src/lib.rs
@@ -28,6 +28,7 @@ mod field_shorthand;
28 28
29use hir::{diagnostics::AnyDiagnostic, Semantics}; 29use hir::{diagnostics::AnyDiagnostic, Semantics};
30use ide_db::{ 30use ide_db::{
31 assists::{Assist, AssistId, AssistKind, AssistResolveStrategy},
31 base_db::{FileId, SourceDatabase}, 32 base_db::{FileId, SourceDatabase},
32 label::Label, 33 label::Label,
33 source_change::SourceChange, 34 source_change::SourceChange,
@@ -42,8 +43,6 @@ use syntax::{
42use text_edit::TextEdit; 43use text_edit::TextEdit;
43use unlinked_file::UnlinkedFile; 44use unlinked_file::UnlinkedFile;
44 45
45use ide_assists::{Assist, AssistId, AssistKind, AssistResolveStrategy};
46
47#[derive(Copy, Clone, Debug, PartialEq)] 46#[derive(Copy, Clone, Debug, PartialEq)]
48pub struct DiagnosticCode(pub &'static str); 47pub struct DiagnosticCode(pub &'static str);
49 48
@@ -265,8 +264,8 @@ fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist {
265#[cfg(test)] 264#[cfg(test)]
266mod tests { 265mod tests {
267 use expect_test::Expect; 266 use expect_test::Expect;
268 use ide_assists::AssistResolveStrategy;
269 use ide_db::{ 267 use ide_db::{
268 assists::AssistResolveStrategy,
270 base_db::{fixture::WithFixture, SourceDatabaseExt}, 269 base_db::{fixture::WithFixture, SourceDatabaseExt},
271 RootDatabase, 270 RootDatabase,
272 }; 271 };
diff --git a/crates/ide_diagnostics/src/missing_fields.rs b/crates/ide_diagnostics/src/missing_fields.rs
index f242ee481..5af67f461 100644
--- a/crates/ide_diagnostics/src/missing_fields.rs
+++ b/crates/ide_diagnostics/src/missing_fields.rs
@@ -1,7 +1,6 @@
1use either::Either; 1use either::Either;
2use hir::{db::AstDatabase, InFile}; 2use hir::{db::AstDatabase, InFile};
3use ide_assists::Assist; 3use ide_db::{assists::Assist, source_change::SourceChange};
4use ide_db::source_change::SourceChange;
5use stdx::format_to; 4use stdx::format_to;
6use syntax::{algo, ast::make, AstNode, SyntaxNodePtr}; 5use syntax::{algo, ast::make, AstNode, SyntaxNodePtr};
7use text_edit::TextEdit; 6use text_edit::TextEdit;
diff --git a/crates/ide_diagnostics/src/missing_ok_or_some_in_tail_expr.rs b/crates/ide_diagnostics/src/missing_ok_or_some_in_tail_expr.rs
index 9e36ca296..01c79b6f5 100644
--- a/crates/ide_diagnostics/src/missing_ok_or_some_in_tail_expr.rs
+++ b/crates/ide_diagnostics/src/missing_ok_or_some_in_tail_expr.rs
@@ -1,6 +1,5 @@
1use hir::db::AstDatabase; 1use hir::db::AstDatabase;
2use ide_assists::Assist; 2use ide_db::{assists::Assist, source_change::SourceChange};
3use ide_db::source_change::SourceChange;
4use syntax::AstNode; 3use syntax::AstNode;
5use text_edit::TextEdit; 4use text_edit::TextEdit;
6 5
diff --git a/crates/ide_diagnostics/src/unresolved_module.rs b/crates/ide_diagnostics/src/unresolved_module.rs
index b11e71b3e..5aa9dae17 100644
--- a/crates/ide_diagnostics/src/unresolved_module.rs
+++ b/crates/ide_diagnostics/src/unresolved_module.rs
@@ -1,6 +1,5 @@
1use hir::db::AstDatabase; 1use hir::db::AstDatabase;
2use ide_assists::Assist; 2use ide_db::{assists::Assist, base_db::AnchoredPathBuf, source_change::FileSystemEdit};
3use ide_db::{base_db::AnchoredPathBuf, source_change::FileSystemEdit};
4use syntax::AstNode; 3use syntax::AstNode;
5 4
6use crate::{fix, Diagnostic, DiagnosticsContext}; 5use crate::{fix, Diagnostic, DiagnosticsContext};