mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge #8498
8498: feat: improve performance by delaying computation of fixes for diagnostics r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
6081b437cc
@ -84,6 +84,7 @@ pub struct DiagnosticsConfig {
|
|||||||
pub(crate) fn diagnostics(
|
pub(crate) fn diagnostics(
|
||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
config: &DiagnosticsConfig,
|
config: &DiagnosticsConfig,
|
||||||
|
resolve: bool,
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
) -> Vec<Diagnostic> {
|
) -> Vec<Diagnostic> {
|
||||||
let _p = profile::span("diagnostics");
|
let _p = profile::span("diagnostics");
|
||||||
@ -107,25 +108,25 @@ pub(crate) fn diagnostics(
|
|||||||
let res = RefCell::new(res);
|
let res = RefCell::new(res);
|
||||||
let sink_builder = DiagnosticSinkBuilder::new()
|
let sink_builder = DiagnosticSinkBuilder::new()
|
||||||
.on::<hir::diagnostics::UnresolvedModule, _>(|d| {
|
.on::<hir::diagnostics::UnresolvedModule, _>(|d| {
|
||||||
res.borrow_mut().push(diagnostic_with_fix(d, &sema));
|
res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve));
|
||||||
})
|
})
|
||||||
.on::<hir::diagnostics::MissingFields, _>(|d| {
|
.on::<hir::diagnostics::MissingFields, _>(|d| {
|
||||||
res.borrow_mut().push(diagnostic_with_fix(d, &sema));
|
res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve));
|
||||||
})
|
})
|
||||||
.on::<hir::diagnostics::MissingOkOrSomeInTailExpr, _>(|d| {
|
.on::<hir::diagnostics::MissingOkOrSomeInTailExpr, _>(|d| {
|
||||||
res.borrow_mut().push(diagnostic_with_fix(d, &sema));
|
res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve));
|
||||||
})
|
})
|
||||||
.on::<hir::diagnostics::NoSuchField, _>(|d| {
|
.on::<hir::diagnostics::NoSuchField, _>(|d| {
|
||||||
res.borrow_mut().push(diagnostic_with_fix(d, &sema));
|
res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve));
|
||||||
})
|
})
|
||||||
.on::<hir::diagnostics::RemoveThisSemicolon, _>(|d| {
|
.on::<hir::diagnostics::RemoveThisSemicolon, _>(|d| {
|
||||||
res.borrow_mut().push(diagnostic_with_fix(d, &sema));
|
res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve));
|
||||||
})
|
})
|
||||||
.on::<hir::diagnostics::IncorrectCase, _>(|d| {
|
.on::<hir::diagnostics::IncorrectCase, _>(|d| {
|
||||||
res.borrow_mut().push(warning_with_fix(d, &sema));
|
res.borrow_mut().push(warning_with_fix(d, &sema, resolve));
|
||||||
})
|
})
|
||||||
.on::<hir::diagnostics::ReplaceFilterMapNextWithFindMap, _>(|d| {
|
.on::<hir::diagnostics::ReplaceFilterMapNextWithFindMap, _>(|d| {
|
||||||
res.borrow_mut().push(warning_with_fix(d, &sema));
|
res.borrow_mut().push(warning_with_fix(d, &sema, resolve));
|
||||||
})
|
})
|
||||||
.on::<hir::diagnostics::InactiveCode, _>(|d| {
|
.on::<hir::diagnostics::InactiveCode, _>(|d| {
|
||||||
// If there's inactive code somewhere in a macro, don't propagate to the call-site.
|
// If there's inactive code somewhere in a macro, don't propagate to the call-site.
|
||||||
@ -152,7 +153,7 @@ pub(crate) fn diagnostics(
|
|||||||
// Override severity and mark as unused.
|
// Override severity and mark as unused.
|
||||||
res.borrow_mut().push(
|
res.borrow_mut().push(
|
||||||
Diagnostic::hint(range, d.message())
|
Diagnostic::hint(range, d.message())
|
||||||
.with_fix(d.fix(&sema))
|
.with_fix(d.fix(&sema, resolve))
|
||||||
.with_code(Some(d.code())),
|
.with_code(Some(d.code())),
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -208,15 +209,23 @@ pub(crate) fn diagnostics(
|
|||||||
res.into_inner()
|
res.into_inner()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic {
|
fn diagnostic_with_fix<D: DiagnosticWithFix>(
|
||||||
|
d: &D,
|
||||||
|
sema: &Semantics<RootDatabase>,
|
||||||
|
resolve: bool,
|
||||||
|
) -> Diagnostic {
|
||||||
Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message())
|
Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message())
|
||||||
.with_fix(d.fix(&sema))
|
.with_fix(d.fix(&sema, resolve))
|
||||||
.with_code(Some(d.code()))
|
.with_code(Some(d.code()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warning_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic {
|
fn warning_with_fix<D: DiagnosticWithFix>(
|
||||||
|
d: &D,
|
||||||
|
sema: &Semantics<RootDatabase>,
|
||||||
|
resolve: bool,
|
||||||
|
) -> Diagnostic {
|
||||||
Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message())
|
Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message())
|
||||||
.with_fix(d.fix(&sema))
|
.with_fix(d.fix(&sema, resolve))
|
||||||
.with_code(Some(d.code()))
|
.with_code(Some(d.code()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,13 +280,19 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fix(id: &'static str, label: &str, source_change: SourceChange, target: TextRange) -> Assist {
|
fn fix(id: &'static str, label: &str, source_change: SourceChange, target: TextRange) -> Assist {
|
||||||
|
let mut res = unresolved_fix(id, label, target);
|
||||||
|
res.source_change = Some(source_change);
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist {
|
||||||
assert!(!id.contains(' '));
|
assert!(!id.contains(' '));
|
||||||
Assist {
|
Assist {
|
||||||
id: AssistId(id, AssistKind::QuickFix),
|
id: AssistId(id, AssistKind::QuickFix),
|
||||||
label: Label::new(label),
|
label: Label::new(label),
|
||||||
group: None,
|
group: None,
|
||||||
target,
|
target,
|
||||||
source_change: Some(source_change),
|
source_change: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +314,7 @@ mod tests {
|
|||||||
|
|
||||||
let (analysis, file_position) = fixture::position(ra_fixture_before);
|
let (analysis, file_position) = fixture::position(ra_fixture_before);
|
||||||
let diagnostic = analysis
|
let diagnostic = analysis
|
||||||
.diagnostics(&DiagnosticsConfig::default(), file_position.file_id)
|
.diagnostics(&DiagnosticsConfig::default(), true, file_position.file_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.pop()
|
.pop()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -328,7 +343,7 @@ mod tests {
|
|||||||
fn check_no_fix(ra_fixture: &str) {
|
fn check_no_fix(ra_fixture: &str) {
|
||||||
let (analysis, file_position) = fixture::position(ra_fixture);
|
let (analysis, file_position) = fixture::position(ra_fixture);
|
||||||
let diagnostic = analysis
|
let diagnostic = analysis
|
||||||
.diagnostics(&DiagnosticsConfig::default(), file_position.file_id)
|
.diagnostics(&DiagnosticsConfig::default(), true, file_position.file_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.pop()
|
.pop()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -342,7 +357,7 @@ mod tests {
|
|||||||
let diagnostics = files
|
let diagnostics = files
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|file_id| {
|
.flat_map(|file_id| {
|
||||||
analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap()
|
analysis.diagnostics(&DiagnosticsConfig::default(), true, file_id).unwrap()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics);
|
assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics);
|
||||||
@ -350,7 +365,8 @@ mod tests {
|
|||||||
|
|
||||||
fn check_expect(ra_fixture: &str, expect: Expect) {
|
fn check_expect(ra_fixture: &str, expect: Expect) {
|
||||||
let (analysis, file_id) = fixture::file(ra_fixture);
|
let (analysis, file_id) = fixture::file(ra_fixture);
|
||||||
let diagnostics = analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap();
|
let diagnostics =
|
||||||
|
analysis.diagnostics(&DiagnosticsConfig::default(), true, file_id).unwrap();
|
||||||
expect.assert_debug_eq(&diagnostics)
|
expect.assert_debug_eq(&diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -895,10 +911,11 @@ struct Foo {
|
|||||||
|
|
||||||
let (analysis, file_id) = fixture::file(r#"mod foo;"#);
|
let (analysis, file_id) = fixture::file(r#"mod foo;"#);
|
||||||
|
|
||||||
let diagnostics = analysis.diagnostics(&config, file_id).unwrap();
|
let diagnostics = analysis.diagnostics(&config, true, file_id).unwrap();
|
||||||
assert!(diagnostics.is_empty());
|
assert!(diagnostics.is_empty());
|
||||||
|
|
||||||
let diagnostics = analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap();
|
let diagnostics =
|
||||||
|
analysis.diagnostics(&DiagnosticsConfig::default(), true, file_id).unwrap();
|
||||||
assert!(!diagnostics.is_empty());
|
assert!(!diagnostics.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1004,8 +1021,9 @@ impl TestStruct {
|
|||||||
let expected = r#"fn foo() {}"#;
|
let expected = r#"fn foo() {}"#;
|
||||||
|
|
||||||
let (analysis, file_position) = fixture::position(input);
|
let (analysis, file_position) = fixture::position(input);
|
||||||
let diagnostics =
|
let diagnostics = analysis
|
||||||
analysis.diagnostics(&DiagnosticsConfig::default(), file_position.file_id).unwrap();
|
.diagnostics(&DiagnosticsConfig::default(), true, file_position.file_id)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(diagnostics.len(), 1);
|
assert_eq!(diagnostics.len(), 1);
|
||||||
|
|
||||||
check_fix(input, expected);
|
check_fix(input, expected);
|
||||||
|
@ -20,17 +20,26 @@ use syntax::{
|
|||||||
};
|
};
|
||||||
use text_edit::TextEdit;
|
use text_edit::TextEdit;
|
||||||
|
|
||||||
use crate::{diagnostics::fix, references::rename::rename_with_semantics, Assist, FilePosition};
|
use crate::{
|
||||||
|
diagnostics::{fix, unresolved_fix},
|
||||||
|
references::rename::rename_with_semantics,
|
||||||
|
Assist, FilePosition,
|
||||||
|
};
|
||||||
|
|
||||||
/// A [Diagnostic] that potentially has a fix available.
|
/// A [Diagnostic] that potentially has a fix available.
|
||||||
///
|
///
|
||||||
/// [Diagnostic]: hir::diagnostics::Diagnostic
|
/// [Diagnostic]: hir::diagnostics::Diagnostic
|
||||||
pub(crate) trait DiagnosticWithFix: Diagnostic {
|
pub(crate) trait DiagnosticWithFix: Diagnostic {
|
||||||
fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist>;
|
/// `resolve` determines if the diagnostic should fill in the `edit` field
|
||||||
|
/// of the assist.
|
||||||
|
///
|
||||||
|
/// If `resolve` is false, the edit will be computed later, on demand, and
|
||||||
|
/// can be omitted.
|
||||||
|
fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiagnosticWithFix for UnresolvedModule {
|
impl DiagnosticWithFix for UnresolvedModule {
|
||||||
fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> {
|
fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
|
||||||
let root = sema.db.parse_or_expand(self.file)?;
|
let root = sema.db.parse_or_expand(self.file)?;
|
||||||
let unresolved_module = self.decl.to_node(&root);
|
let unresolved_module = self.decl.to_node(&root);
|
||||||
Some(fix(
|
Some(fix(
|
||||||
@ -50,7 +59,7 @@ impl DiagnosticWithFix for UnresolvedModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DiagnosticWithFix for NoSuchField {
|
impl DiagnosticWithFix for NoSuchField {
|
||||||
fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> {
|
fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
|
||||||
let root = sema.db.parse_or_expand(self.file)?;
|
let root = sema.db.parse_or_expand(self.file)?;
|
||||||
missing_record_expr_field_fix(
|
missing_record_expr_field_fix(
|
||||||
&sema,
|
&sema,
|
||||||
@ -61,7 +70,7 @@ impl DiagnosticWithFix for NoSuchField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DiagnosticWithFix for MissingFields {
|
impl DiagnosticWithFix for MissingFields {
|
||||||
fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> {
|
fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
|
||||||
// Note that although we could add a diagnostics to
|
// Note that although we could add a diagnostics to
|
||||||
// fill the missing tuple field, e.g :
|
// fill the missing tuple field, e.g :
|
||||||
// `struct A(usize);`
|
// `struct A(usize);`
|
||||||
@ -97,7 +106,7 @@ impl DiagnosticWithFix for MissingFields {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
|
impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
|
||||||
fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> {
|
fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
|
||||||
let root = sema.db.parse_or_expand(self.file)?;
|
let root = sema.db.parse_or_expand(self.file)?;
|
||||||
let tail_expr = self.expr.to_node(&root);
|
let tail_expr = self.expr.to_node(&root);
|
||||||
let tail_expr_range = tail_expr.syntax().text_range();
|
let tail_expr_range = tail_expr.syntax().text_range();
|
||||||
@ -110,7 +119,7 @@ impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DiagnosticWithFix for RemoveThisSemicolon {
|
impl DiagnosticWithFix for RemoveThisSemicolon {
|
||||||
fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> {
|
fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
|
||||||
let root = sema.db.parse_or_expand(self.file)?;
|
let root = sema.db.parse_or_expand(self.file)?;
|
||||||
|
|
||||||
let semicolon = self
|
let semicolon = self
|
||||||
@ -130,7 +139,7 @@ impl DiagnosticWithFix for RemoveThisSemicolon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DiagnosticWithFix for IncorrectCase {
|
impl DiagnosticWithFix for IncorrectCase {
|
||||||
fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> {
|
fn fix(&self, sema: &Semantics<RootDatabase>, resolve: bool) -> Option<Assist> {
|
||||||
let root = sema.db.parse_or_expand(self.file)?;
|
let root = sema.db.parse_or_expand(self.file)?;
|
||||||
let name_node = self.ident.to_node(&root);
|
let name_node = self.ident.to_node(&root);
|
||||||
|
|
||||||
@ -138,16 +147,19 @@ impl DiagnosticWithFix for IncorrectCase {
|
|||||||
let frange = name_node.original_file_range(sema.db);
|
let frange = name_node.original_file_range(sema.db);
|
||||||
let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
|
let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
|
||||||
|
|
||||||
let rename_changes =
|
|
||||||
rename_with_semantics(sema, file_position, &self.suggested_text).ok()?;
|
|
||||||
|
|
||||||
let label = format!("Rename to {}", self.suggested_text);
|
let label = format!("Rename to {}", self.suggested_text);
|
||||||
Some(fix("change_case", &label, rename_changes, frange.range))
|
let mut res = unresolved_fix("change_case", &label, frange.range);
|
||||||
|
if resolve {
|
||||||
|
let source_change = rename_with_semantics(sema, file_position, &self.suggested_text);
|
||||||
|
res.source_change = Some(source_change.ok().unwrap_or_default());
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap {
|
impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap {
|
||||||
fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> {
|
fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
|
||||||
let root = sema.db.parse_or_expand(self.file)?;
|
let root = sema.db.parse_or_expand(self.file)?;
|
||||||
let next_expr = self.next_expr.to_node(&root);
|
let next_expr = self.next_expr.to_node(&root);
|
||||||
let next_call = ast::MethodCallExpr::cast(next_expr.syntax().clone())?;
|
let next_call = ast::MethodCallExpr::cast(next_expr.syntax().clone())?;
|
||||||
|
@ -50,7 +50,7 @@ impl Diagnostic for UnlinkedFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DiagnosticWithFix for UnlinkedFile {
|
impl DiagnosticWithFix for UnlinkedFile {
|
||||||
fn fix(&self, sema: &hir::Semantics<RootDatabase>) -> Option<Assist> {
|
fn fix(&self, sema: &hir::Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
|
||||||
// If there's an existing module that could add a `mod` item to include the unlinked file,
|
// If there's an existing module that could add a `mod` item to include the unlinked file,
|
||||||
// suggest that as a fix.
|
// suggest that as a fix.
|
||||||
|
|
||||||
|
@ -526,9 +526,39 @@ impl Analysis {
|
|||||||
pub fn diagnostics(
|
pub fn diagnostics(
|
||||||
&self,
|
&self,
|
||||||
config: &DiagnosticsConfig,
|
config: &DiagnosticsConfig,
|
||||||
|
resolve: bool,
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
) -> Cancelable<Vec<Diagnostic>> {
|
) -> Cancelable<Vec<Diagnostic>> {
|
||||||
self.with_db(|db| diagnostics::diagnostics(db, config, file_id))
|
self.with_db(|db| diagnostics::diagnostics(db, config, resolve, file_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience function to return assists + quick fixes for diagnostics
|
||||||
|
pub fn assists_with_fixes(
|
||||||
|
&self,
|
||||||
|
assist_config: &AssistConfig,
|
||||||
|
diagnostics_config: &DiagnosticsConfig,
|
||||||
|
resolve: bool,
|
||||||
|
frange: FileRange,
|
||||||
|
) -> Cancelable<Vec<Assist>> {
|
||||||
|
let include_fixes = match &assist_config.allowed {
|
||||||
|
Some(it) => it.iter().any(|&it| it == AssistKind::None || it == AssistKind::QuickFix),
|
||||||
|
None => true,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.with_db(|db| {
|
||||||
|
let mut res = Assist::get(db, assist_config, resolve, frange);
|
||||||
|
ssr::add_ssr_assist(db, &mut res, resolve, frange);
|
||||||
|
|
||||||
|
if include_fixes {
|
||||||
|
res.extend(
|
||||||
|
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()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
res
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the edit required to rename reference at the position to the new
|
/// Returns the edit required to rename reference at the position to the new
|
||||||
|
@ -57,7 +57,8 @@ pub fn diagnostics(
|
|||||||
let crate_name =
|
let crate_name =
|
||||||
module.krate().display_name(db).as_deref().unwrap_or("unknown").to_string();
|
module.krate().display_name(db).as_deref().unwrap_or("unknown").to_string();
|
||||||
println!("processing crate: {}, module: {}", crate_name, _vfs.file_path(file_id));
|
println!("processing crate: {}, module: {}", crate_name, _vfs.file_path(file_id));
|
||||||
for diagnostic in analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap()
|
for diagnostic in
|
||||||
|
analysis.diagnostics(&DiagnosticsConfig::default(), false, file_id).unwrap()
|
||||||
{
|
{
|
||||||
if matches!(diagnostic.severity, Severity::Error) {
|
if matches!(diagnostic.severity, Severity::Error) {
|
||||||
found_error = true;
|
found_error = true;
|
||||||
|
@ -8,8 +8,8 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use ide::{
|
use ide::{
|
||||||
AnnotationConfig, AssistKind, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData,
|
AnnotationConfig, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, Query,
|
||||||
Query, RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange, TextEdit,
|
RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange, TextEdit,
|
||||||
};
|
};
|
||||||
use ide_db::SymbolKind;
|
use ide_db::SymbolKind;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@ -1003,27 +1003,13 @@ pub(crate) fn handle_code_action(
|
|||||||
|
|
||||||
let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
|
let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
|
||||||
|
|
||||||
let include_quick_fixes = match &assists_config.allowed {
|
|
||||||
Some(v) => v.iter().any(|it| it == &AssistKind::None || it == &AssistKind::QuickFix),
|
|
||||||
None => true,
|
|
||||||
};
|
|
||||||
let code_action_resolve_cap = snap.config.code_action_resolve();
|
let code_action_resolve_cap = snap.config.code_action_resolve();
|
||||||
|
let assists = snap.analysis.assists_with_fixes(
|
||||||
let mut assists = Vec::new();
|
&assists_config,
|
||||||
|
&snap.config.diagnostics(),
|
||||||
// Fixes from native diagnostics.
|
!code_action_resolve_cap,
|
||||||
if include_quick_fixes {
|
frange,
|
||||||
let diagnostics = snap.analysis.diagnostics(&snap.config.diagnostics(), frange.file_id)?;
|
)?;
|
||||||
assists.extend(
|
|
||||||
diagnostics
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|d| d.fix)
|
|
||||||
.filter(|fix| fix.target.intersect(frange.range).is_some()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assists proper.
|
|
||||||
assists.extend(snap.analysis.assists(&assists_config, !code_action_resolve_cap, frange)?);
|
|
||||||
for (index, assist) in assists.into_iter().enumerate() {
|
for (index, assist) in assists.into_iter().enumerate() {
|
||||||
let resolve_data =
|
let resolve_data =
|
||||||
if code_action_resolve_cap { Some((index, params.clone())) } else { None };
|
if code_action_resolve_cap { Some((index, params.clone())) } else { None };
|
||||||
@ -1066,7 +1052,13 @@ pub(crate) fn handle_code_action_resolve(
|
|||||||
.only
|
.only
|
||||||
.map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
|
.map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
|
||||||
|
|
||||||
let assists = snap.analysis.assists(&assists_config, true, frange)?;
|
let assists = snap.analysis.assists_with_fixes(
|
||||||
|
&assists_config,
|
||||||
|
&snap.config.diagnostics(),
|
||||||
|
true,
|
||||||
|
frange,
|
||||||
|
)?;
|
||||||
|
|
||||||
let (id, index) = split_once(¶ms.id, ':').unwrap();
|
let (id, index) = split_once(¶ms.id, ':').unwrap();
|
||||||
let index = index.parse::<usize>().unwrap();
|
let index = index.parse::<usize>().unwrap();
|
||||||
let assist = &assists[index];
|
let assist = &assists[index];
|
||||||
@ -1190,7 +1182,7 @@ pub(crate) fn publish_diagnostics(
|
|||||||
|
|
||||||
let diagnostics: Vec<Diagnostic> = snap
|
let diagnostics: Vec<Diagnostic> = snap
|
||||||
.analysis
|
.analysis
|
||||||
.diagnostics(&snap.config.diagnostics(), file_id)?
|
.diagnostics(&snap.config.diagnostics(), false, file_id)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|d| Diagnostic {
|
.map(|d| Diagnostic {
|
||||||
range: to_proto::range(&line_index, d.range),
|
range: to_proto::range(&line_index, d.range),
|
||||||
|
@ -168,6 +168,7 @@ impl Server {
|
|||||||
self.send_notification(r)
|
self.send_notification(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
pub(crate) fn request<R>(&self, params: R::Params, expected_resp: Value)
|
pub(crate) fn request<R>(&self, params: R::Params, expected_resp: Value)
|
||||||
where
|
where
|
||||||
R: lsp_types::request::Request,
|
R: lsp_types::request::Request,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user