From a91071b57be6e64ad2fd277998ada0ae6206457b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 14 Jun 2021 13:27:11 +0300 Subject: internal: cut deps between assists and diagnostics --- crates/ide_assists/src/lib.rs | 131 +------------------- crates/ide_db/src/assists.rs | 136 +++++++++++++++++++++ crates/ide_db/src/lib.rs | 1 + crates/ide_diagnostics/Cargo.toml | 1 - crates/ide_diagnostics/src/incorrect_case.rs | 3 +- crates/ide_diagnostics/src/lib.rs | 5 +- crates/ide_diagnostics/src/missing_fields.rs | 3 +- .../src/missing_ok_or_some_in_tail_expr.rs | 3 +- crates/ide_diagnostics/src/unresolved_module.rs | 3 +- 9 files changed, 147 insertions(+), 139 deletions(-) create mode 100644 crates/ide_db/src/assists.rs (limited to 'crates') 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; pub mod utils; pub mod path_transform; -use std::str::FromStr; - use hir::Semantics; -use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, RootDatabase}; +use ide_db::{base_db::FileRange, RootDatabase}; use syntax::TextRange; pub(crate) use crate::assist_context::{AssistContext, Assists}; pub use assist_config::AssistConfig; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum AssistKind { - // FIXME: does the None variant make sense? Probably not. - None, - - QuickFix, - Generate, - Refactor, - RefactorExtract, - RefactorInline, - RefactorRewrite, -} - -impl AssistKind { - pub fn contains(self, other: AssistKind) -> bool { - if self == other { - return true; - } - - match self { - AssistKind::None | AssistKind::Generate => true, - AssistKind::Refactor => match other { - AssistKind::RefactorExtract - | AssistKind::RefactorInline - | AssistKind::RefactorRewrite => true, - _ => false, - }, - _ => false, - } - } - - pub fn name(&self) -> &str { - match self { - AssistKind::None => "None", - AssistKind::QuickFix => "QuickFix", - AssistKind::Generate => "Generate", - AssistKind::Refactor => "Refactor", - AssistKind::RefactorExtract => "RefactorExtract", - AssistKind::RefactorInline => "RefactorInline", - AssistKind::RefactorRewrite => "RefactorRewrite", - } - } -} - -impl FromStr for AssistKind { - type Err = String; - - fn from_str(s: &str) -> Result { - match s { - "None" => Ok(AssistKind::None), - "QuickFix" => Ok(AssistKind::QuickFix), - "Generate" => Ok(AssistKind::Generate), - "Refactor" => Ok(AssistKind::Refactor), - "RefactorExtract" => Ok(AssistKind::RefactorExtract), - "RefactorInline" => Ok(AssistKind::RefactorInline), - "RefactorRewrite" => Ok(AssistKind::RefactorRewrite), - unknown => Err(format!("Unknown AssistKind: '{}'", unknown)), - } - } -} - -/// Unique identifier of the assist, should not be shown to the user -/// directly. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct AssistId(pub &'static str, pub AssistKind); - -/// A way to control how many asssist to resolve during the assist resolution. -/// When an assist is resolved, its edits are calculated that might be costly to always do by default. -#[derive(Debug)] -pub enum AssistResolveStrategy { - /// No assists should be resolved. - None, - /// All assists should be resolved. - All, - /// Only a certain assist should be resolved. - Single(SingleResolve), -} - -/// Hold the [`AssistId`] data of a certain assist to resolve. -/// The original id object cannot be used due to a `'static` lifetime -/// and the requirement to construct this struct dynamically during the resolve handling. -#[derive(Debug)] -pub struct SingleResolve { - /// The id of the assist. - pub assist_id: String, - // The kind of the assist. - pub assist_kind: AssistKind, -} - -impl AssistResolveStrategy { - pub fn should_resolve(&self, id: &AssistId) -> bool { - match self { - AssistResolveStrategy::None => false, - AssistResolveStrategy::All => true, - AssistResolveStrategy::Single(single_resolve) => { - single_resolve.assist_id == id.0 && single_resolve.assist_kind == id.1 - } - } - } -} - -#[derive(Clone, Debug)] -pub struct GroupLabel(pub String); - -#[derive(Debug, Clone)] -pub struct Assist { - pub id: AssistId, - /// Short description of the assist, as shown in the UI. - pub label: Label, - pub group: Option, - /// Target ranges are used to sort assists: the smaller the target range, - /// the more specific assist is, and so it should be sorted first. - pub target: TextRange, - /// Computing source change sometimes is much more costly then computing the - /// other fields. Additionally, the actual change is not required to show - /// the lightbulb UI, it only is needed when the user tries to apply an - /// assist. So, we compute it lazily: the API allow requesting assists with - /// or without source change. We could (and in fact, used to) distinguish - /// between resolved and unresolved assists at the type level, but this is - /// cumbersome, especially if you want to embed an assist into another data - /// structure, such as a diagnostic. - pub source_change: Option, -} +pub use ide_db::assists::{ + Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel, SingleResolve, +}; /// Return all the assists applicable at the given position. pub 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 @@ +//! This module defines the `Assist` data structure. The actual assist live in +//! the `ide_assists` downstream crate. We want to define the data structures in +//! this low-level crate though, because `ide_diagnostics` also need them +//! (fixits for diagnostics and assists are the same thing under the hood). We +//! want to compile `ide_assists` and `ide_diagnostics` in parallel though, so +//! we pull the common definitions upstream, to this crate. + +use std::str::FromStr; + +use syntax::TextRange; + +use crate::{label::Label, source_change::SourceChange}; + +#[derive(Debug, Clone)] +pub struct Assist { + pub id: AssistId, + /// Short description of the assist, as shown in the UI. + pub label: Label, + pub group: Option, + /// Target ranges are used to sort assists: the smaller the target range, + /// the more specific assist is, and so it should be sorted first. + pub target: TextRange, + /// Computing source change sometimes is much more costly then computing the + /// other fields. Additionally, the actual change is not required to show + /// the lightbulb UI, it only is needed when the user tries to apply an + /// assist. So, we compute it lazily: the API allow requesting assists with + /// or without source change. We could (and in fact, used to) distinguish + /// between resolved and unresolved assists at the type level, but this is + /// cumbersome, especially if you want to embed an assist into another data + /// structure, such as a diagnostic. + pub source_change: Option, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum AssistKind { + // FIXME: does the None variant make sense? Probably not. + None, + + QuickFix, + Generate, + Refactor, + RefactorExtract, + RefactorInline, + RefactorRewrite, +} + +impl AssistKind { + pub fn contains(self, other: AssistKind) -> bool { + if self == other { + return true; + } + + match self { + AssistKind::None | AssistKind::Generate => true, + AssistKind::Refactor => match other { + AssistKind::RefactorExtract + | AssistKind::RefactorInline + | AssistKind::RefactorRewrite => true, + _ => false, + }, + _ => false, + } + } + + pub fn name(&self) -> &str { + match self { + AssistKind::None => "None", + AssistKind::QuickFix => "QuickFix", + AssistKind::Generate => "Generate", + AssistKind::Refactor => "Refactor", + AssistKind::RefactorExtract => "RefactorExtract", + AssistKind::RefactorInline => "RefactorInline", + AssistKind::RefactorRewrite => "RefactorRewrite", + } + } +} + +impl FromStr for AssistKind { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "None" => Ok(AssistKind::None), + "QuickFix" => Ok(AssistKind::QuickFix), + "Generate" => Ok(AssistKind::Generate), + "Refactor" => Ok(AssistKind::Refactor), + "RefactorExtract" => Ok(AssistKind::RefactorExtract), + "RefactorInline" => Ok(AssistKind::RefactorInline), + "RefactorRewrite" => Ok(AssistKind::RefactorRewrite), + unknown => Err(format!("Unknown AssistKind: '{}'", unknown)), + } + } +} + +/// Unique identifier of the assist, should not be shown to the user +/// directly. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct AssistId(pub &'static str, pub AssistKind); + +/// A way to control how many asssist to resolve during the assist resolution. +/// When an assist is resolved, its edits are calculated that might be costly to always do by default. +#[derive(Debug)] +pub enum AssistResolveStrategy { + /// No assists should be resolved. + None, + /// All assists should be resolved. + All, + /// Only a certain assist should be resolved. + Single(SingleResolve), +} + +/// Hold the [`AssistId`] data of a certain assist to resolve. +/// The original id object cannot be used due to a `'static` lifetime +/// and the requirement to construct this struct dynamically during the resolve handling. +#[derive(Debug)] +pub struct SingleResolve { + /// The id of the assist. + pub assist_id: String, + // The kind of the assist. + pub assist_kind: AssistKind, +} + +impl AssistResolveStrategy { + pub fn should_resolve(&self, id: &AssistId) -> bool { + match self { + AssistResolveStrategy::None => false, + AssistResolveStrategy::All => true, + AssistResolveStrategy::Single(single_resolve) => { + single_resolve.assist_id == id.0 && single_resolve.assist_kind == id.1 + } + } + } +} + +#[derive(Clone, Debug)] +pub 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 @@ //! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search. mod apply_change; +pub mod assists; pub mod label; pub mod line_index; pub 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" } cfg = { path = "../cfg", version = "0.0.0" } hir = { path = "../hir", version = "0.0.0" } ide_db = { path = "../ide_db", version = "0.0.0" } -ide_assists = { path = "../ide_assists", version = "0.0.0" } [dev-dependencies] expect-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 @@ use hir::{db::AstDatabase, InFile}; -use ide_assists::Assist; -use ide_db::base_db::FilePosition; +use ide_db::{assists::Assist, base_db::FilePosition}; use syntax::AstNode; use 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; use hir::{diagnostics::AnyDiagnostic, Semantics}; use ide_db::{ + assists::{Assist, AssistId, AssistKind, AssistResolveStrategy}, base_db::{FileId, SourceDatabase}, label::Label, source_change::SourceChange, @@ -42,8 +43,6 @@ use syntax::{ use text_edit::TextEdit; use unlinked_file::UnlinkedFile; -use ide_assists::{Assist, AssistId, AssistKind, AssistResolveStrategy}; - #[derive(Copy, Clone, Debug, PartialEq)] pub struct DiagnosticCode(pub &'static str); @@ -265,8 +264,8 @@ fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist { #[cfg(test)] mod tests { use expect_test::Expect; - use ide_assists::AssistResolveStrategy; use ide_db::{ + assists::AssistResolveStrategy, base_db::{fixture::WithFixture, SourceDatabaseExt}, RootDatabase, }; 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 @@ use either::Either; use hir::{db::AstDatabase, InFile}; -use ide_assists::Assist; -use ide_db::source_change::SourceChange; +use ide_db::{assists::Assist, source_change::SourceChange}; use stdx::format_to; use syntax::{algo, ast::make, AstNode, SyntaxNodePtr}; use 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 @@ use hir::db::AstDatabase; -use ide_assists::Assist; -use ide_db::source_change::SourceChange; +use ide_db::{assists::Assist, source_change::SourceChange}; use syntax::AstNode; use text_edit::TextEdit; 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 @@ use hir::db::AstDatabase; -use ide_assists::Assist; -use ide_db::{base_db::AnchoredPathBuf, source_change::FileSystemEdit}; +use ide_db::{assists::Assist, base_db::AnchoredPathBuf, source_change::FileSystemEdit}; use syntax::AstNode; use crate::{fix, Diagnostic, DiagnosticsContext}; -- cgit v1.2.3