mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
Resolve single assist only
This commit is contained in:
parent
e5cdcb8b12
commit
1679a376f3
9 changed files with 78 additions and 32 deletions
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(¶ms.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)
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue