Resolve single assist only

This commit is contained in:
Kirill Bulatov 2021-05-03 18:03:28 +03:00
parent e5cdcb8b12
commit 1679a376f3
9 changed files with 78 additions and 32 deletions

View file

@ -85,7 +85,7 @@ pub struct DiagnosticsConfig {
pub(crate) fn diagnostics(
db: &RootDatabase,
config: &DiagnosticsConfig,
resolve: AssistResolveStrategy,
resolve: &AssistResolveStrategy,
file_id: FileId,
) -> Vec<Diagnostic> {
let _p = profile::span("diagnostics");
@ -213,7 +213,7 @@ pub(crate) fn diagnostics(
fn diagnostic_with_fix<D: DiagnosticWithFix>(
d: &D,
sema: &Semantics<RootDatabase>,
resolve: AssistResolveStrategy,
resolve: &AssistResolveStrategy,
) -> Diagnostic {
Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message())
.with_fix(d.fix(&sema, resolve))
@ -223,7 +223,7 @@ fn diagnostic_with_fix<D: DiagnosticWithFix>(
fn warning_with_fix<D: DiagnosticWithFix>(
d: &D,
sema: &Semantics<RootDatabase>,
resolve: AssistResolveStrategy,
resolve: &AssistResolveStrategy,
) -> Diagnostic {
Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message())
.with_fix(d.fix(&sema, resolve))

View file

@ -39,7 +39,7 @@ pub(crate) trait DiagnosticWithFix: Diagnostic {
fn fix(
&self,
sema: &Semantics<RootDatabase>,
_resolve: AssistResolveStrategy,
_resolve: &AssistResolveStrategy,
) -> Option<Assist>;
}
@ -47,7 +47,7 @@ impl DiagnosticWithFix for UnresolvedModule {
fn fix(
&self,
sema: &Semantics<RootDatabase>,
_resolve: AssistResolveStrategy,
_resolve: &AssistResolveStrategy,
) -> Option<Assist> {
let root = sema.db.parse_or_expand(self.file)?;
let unresolved_module = self.decl.to_node(&root);
@ -71,7 +71,7 @@ impl DiagnosticWithFix for NoSuchField {
fn fix(
&self,
sema: &Semantics<RootDatabase>,
_resolve: AssistResolveStrategy,
_resolve: &AssistResolveStrategy,
) -> Option<Assist> {
let root = sema.db.parse_or_expand(self.file)?;
missing_record_expr_field_fix(
@ -86,7 +86,7 @@ impl DiagnosticWithFix for MissingFields {
fn fix(
&self,
sema: &Semantics<RootDatabase>,
_resolve: AssistResolveStrategy,
_resolve: &AssistResolveStrategy,
) -> Option<Assist> {
// Note that although we could add a diagnostics to
// fill the missing tuple field, e.g :
@ -126,7 +126,7 @@ impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
fn fix(
&self,
sema: &Semantics<RootDatabase>,
_resolve: AssistResolveStrategy,
_resolve: &AssistResolveStrategy,
) -> Option<Assist> {
let root = sema.db.parse_or_expand(self.file)?;
let tail_expr = self.expr.to_node(&root);
@ -143,7 +143,7 @@ impl DiagnosticWithFix for RemoveThisSemicolon {
fn fix(
&self,
sema: &Semantics<RootDatabase>,
_resolve: AssistResolveStrategy,
_resolve: &AssistResolveStrategy,
) -> Option<Assist> {
let root = sema.db.parse_or_expand(self.file)?;
@ -167,7 +167,7 @@ impl DiagnosticWithFix for IncorrectCase {
fn fix(
&self,
sema: &Semantics<RootDatabase>,
resolve: AssistResolveStrategy,
resolve: &AssistResolveStrategy,
) -> Option<Assist> {
let root = sema.db.parse_or_expand(self.file)?;
let name_node = self.ident.to_node(&root);
@ -191,7 +191,7 @@ impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap {
fn fix(
&self,
sema: &Semantics<RootDatabase>,
_resolve: AssistResolveStrategy,
_resolve: &AssistResolveStrategy,
) -> Option<Assist> {
let root = sema.db.parse_or_expand(self.file)?;
let next_expr = self.next_expr.to_node(&root);

View file

@ -54,7 +54,7 @@ impl DiagnosticWithFix for UnlinkedFile {
fn fix(
&self,
sema: &hir::Semantics<RootDatabase>,
_resolve: AssistResolveStrategy,
_resolve: &AssistResolveStrategy,
) -> Option<Assist> {
// If there's an existing module that could add a `mod` item to include the unlinked file,
// suggest that as a fix.

View file

@ -522,7 +522,7 @@ impl Analysis {
frange: FileRange,
) -> Cancelable<Vec<Assist>> {
self.with_db(|db| {
let ssr_assists = ssr::ssr_assists(db, resolve, frange);
let ssr_assists = ssr::ssr_assists(db, &resolve, frange);
let mut acc = Assist::get(db, config, resolve, frange);
acc.extend(ssr_assists.into_iter());
acc
@ -536,7 +536,7 @@ impl Analysis {
resolve: AssistResolveStrategy,
file_id: FileId,
) -> Cancelable<Vec<Diagnostic>> {
self.with_db(|db| diagnostics::diagnostics(db, config, resolve, file_id))
self.with_db(|db| diagnostics::diagnostics(db, config, &resolve, file_id))
}
/// Convenience function to return assists + quick fixes for diagnostics
@ -553,9 +553,9 @@ impl Analysis {
};
self.with_db(|db| {
let ssr_assists = ssr::ssr_assists(db, resolve, frange);
let ssr_assists = ssr::ssr_assists(db, &resolve, frange);
let diagnostic_assists = if include_fixes {
diagnostics::diagnostics(db, diagnostics_config, resolve, frange.file_id)
diagnostics::diagnostics(db, diagnostics_config, &resolve, frange.file_id)
.into_iter()
.filter_map(|it| it.fix)
.filter(|it| it.target.intersect(frange.range).is_some())

View file

@ -7,7 +7,7 @@ use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, Root
pub(crate) fn ssr_assists(
db: &RootDatabase,
resolve: AssistResolveStrategy,
resolve: &AssistResolveStrategy,
frange: FileRange,
) -> Vec<Assist> {
let mut ssr_assists = Vec::with_capacity(2);
@ -73,7 +73,7 @@ mod tests {
let mut local_roots = FxHashSet::default();
local_roots.insert(ide_db::base_db::fixture::WORKSPACE);
db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
ssr_assists(&db, resolve, FileRange { file_id, range: range_or_offset.into() })
ssr_assists(&db, &resolve, FileRange { file_id, range: range_or_offset.into() })
}
#[test]

View file

@ -17,6 +17,8 @@ mod tests;
pub mod utils;
pub mod ast_transform;
use std::str::FromStr;
use hir::Semantics;
use ide_db::base_db::FileRange;
use ide_db::{label::Label, source_change::SourceChange, RootDatabase};
@ -56,6 +58,35 @@ impl AssistKind {
_ => return 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<Self, Self::Err> {
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
@ -64,11 +95,11 @@ impl AssistKind {
pub struct AssistId(pub &'static str, pub AssistKind);
// TODO kb docs
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)]
pub enum AssistResolveStrategy {
None,
All,
Single(AssistId),
Single(String, AssistKind),
}
impl AssistResolveStrategy {
@ -76,7 +107,9 @@ impl AssistResolveStrategy {
match self {
AssistResolveStrategy::None => false,
AssistResolveStrategy::All => true,
AssistResolveStrategy::Single(id_to_resolve) => id_to_resolve == id,
AssistResolveStrategy::Single(id_to_resolve, kind) => {
id_to_resolve == id.0 && kind == &id.1
}
}
}
}

View file

@ -8,9 +8,9 @@ use std::{
};
use ide::{
AnnotationConfig, AssistResolveStrategy, FileId, FilePosition, FileRange, HoverAction,
HoverGotoTypeData, Query, RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange,
TextEdit,
AnnotationConfig, AssistKind, AssistResolveStrategy, FileId, FilePosition, FileRange,
HoverAction, HoverGotoTypeData, Query, RangeInfo, Runnable, RunnableKind, SearchScope,
SourceChange, TextEdit,
};
use ide_db::SymbolKind;
use itertools::Itertools;
@ -28,7 +28,7 @@ use lsp_types::{
use project_model::TargetKind;
use serde::{Deserialize, Serialize};
use serde_json::to_value;
use stdx::{format_to, split_once};
use stdx::format_to;
use syntax::{algo, ast, AstNode, TextRange, TextSize};
use crate::{
@ -1058,18 +1058,27 @@ pub(crate) fn handle_code_action_resolve(
.only
.map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
let assist_kind: AssistKind = match params.kind.parse() {
Ok(kind) => kind,
Err(e) => {
return Err(LspError::new(
ErrorCode::InvalidParams as i32,
format!("For the assist to resolve, failed to parse the kind: {}", e),
)
.into())
}
};
let assists = snap.analysis.assists_with_fixes(
&assists_config,
&snap.config.diagnostics(),
// TODO kb pass a certain id
AssistResolveStrategy::All,
AssistResolveStrategy::Single(params.id.clone(), assist_kind),
frange,
)?;
let (id, index) = split_once(&params.id, ':').unwrap();
let index = index.parse::<usize>().unwrap();
let assist = &assists[index];
assert!(assist.id.0 == id);
let assist = &assists[params.index];
assert!(assist.id.0 == params.id);
assert!(assist.id.1 == assist_kind);
let edit = to_proto::code_action(&snap, assist.clone(), None)?.edit;
code_action.edit = edit;
Ok(code_action)

View file

@ -303,6 +303,8 @@ pub struct CodeAction {
pub struct CodeActionData {
pub code_action_params: lsp_types::CodeActionParams,
pub id: String,
pub kind: String,
pub index: usize,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]

View file

@ -897,8 +897,10 @@ pub(crate) fn code_action(
(Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?),
(None, Some((index, code_action_params))) => {
res.data = Some(lsp_ext::CodeActionData {
id: format!("{}:{}", assist.id.0, index.to_string()),
id: assist.id.0.to_string(),
code_action_params,
kind: assist.id.1.name().to_string(),
index,
});
}
(None, None) => {