mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-03 13:23:25 +00:00
Add expression fill mode variant for filling with underscore expressions
This commit is contained in:
parent
8fb2dcc947
commit
7e526b6be7
31 changed files with 172 additions and 125 deletions
|
|
@ -5,9 +5,13 @@ use hir::{
|
|||
sym,
|
||||
};
|
||||
use ide_db::{
|
||||
FxHashMap, assists::Assist, famous_defs::FamousDefs,
|
||||
imports::import_assets::item_for_path_search, source_change::SourceChange,
|
||||
syntax_helpers::tree_diff::diff, text_edit::TextEdit,
|
||||
FxHashMap,
|
||||
assists::{Assist, ExprFillDefaultMode},
|
||||
famous_defs::FamousDefs,
|
||||
imports::import_assets::item_for_path_search,
|
||||
source_change::SourceChange,
|
||||
syntax_helpers::tree_diff::diff,
|
||||
text_edit::TextEdit,
|
||||
use_trivial_constructor::use_trivial_constructor,
|
||||
};
|
||||
use stdx::format_to;
|
||||
|
|
@ -102,8 +106,9 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
|
|||
});
|
||||
|
||||
let generate_fill_expr = |ty: &Type| match ctx.config.expr_fill_default {
|
||||
crate::ExprFillDefaultMode::Todo => make::ext::expr_todo(),
|
||||
crate::ExprFillDefaultMode::Default => {
|
||||
ExprFillDefaultMode::Todo => make::ext::expr_todo(),
|
||||
ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
|
||||
ExprFillDefaultMode::Default => {
|
||||
get_default_constructor(ctx, d, ty).unwrap_or_else(make::ext::expr_todo)
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::ops::Not;
|
||||
|
||||
use hir::{
|
||||
ClosureStyle, HirDisplay, ImportPathConfig,
|
||||
db::ExpandDatabase,
|
||||
|
|
@ -60,9 +62,13 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
|
|||
|
||||
let mut formatter = |_: &hir::Type| String::from("_");
|
||||
|
||||
let assists: Vec<Assist> = paths
|
||||
let assists: Vec<Assist> = d
|
||||
.expected
|
||||
.is_unknown()
|
||||
.not()
|
||||
.then(|| "todo!()".to_owned())
|
||||
.into_iter()
|
||||
.filter_map(|path| {
|
||||
.chain(paths.into_iter().filter_map(|path| {
|
||||
path.gen_source_code(
|
||||
&scope,
|
||||
&mut formatter,
|
||||
|
|
@ -75,7 +81,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
|
|||
ctx.display_target,
|
||||
)
|
||||
.ok()
|
||||
})
|
||||
}))
|
||||
.unique()
|
||||
.map(|code| Assist {
|
||||
id: AssistId::quick_fix("typed-hole"),
|
||||
|
|
@ -95,9 +101,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::{
|
||||
check_diagnostics, check_fixes_unordered, check_has_fix, check_has_single_fix,
|
||||
};
|
||||
use crate::tests::{check_diagnostics, check_fixes_unordered, check_has_fix};
|
||||
|
||||
#[test]
|
||||
fn unknown() {
|
||||
|
|
@ -119,9 +123,9 @@ fn main() {
|
|||
if _ {}
|
||||
//^ 💡 error: invalid `_` expression, expected type `bool`
|
||||
let _: fn() -> i32 = _;
|
||||
//^ error: invalid `_` expression, expected type `fn() -> i32`
|
||||
//^ 💡 error: invalid `_` expression, expected type `fn() -> i32`
|
||||
let _: fn() -> () = _; // FIXME: This should trigger an assist because `main` matches via *coercion*
|
||||
//^ error: invalid `_` expression, expected type `fn()`
|
||||
//^ 💡 error: invalid `_` expression, expected type `fn()`
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
|
@ -147,7 +151,7 @@ fn main() {
|
|||
fn main() {
|
||||
let mut x = t();
|
||||
x = _;
|
||||
//^ error: invalid `_` expression, expected type `&str`
|
||||
//^ 💡 error: invalid `_` expression, expected type `&str`
|
||||
x = "";
|
||||
}
|
||||
fn t<T>() -> T { loop {} }
|
||||
|
|
@ -308,7 +312,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn ignore_impl_func_with_incorrect_return() {
|
||||
check_has_single_fix(
|
||||
check_fixes_unordered(
|
||||
r#"
|
||||
struct Bar {}
|
||||
trait Foo {
|
||||
|
|
@ -323,7 +327,8 @@ fn main() {
|
|||
let a: i32 = 1;
|
||||
let c: Bar = _$0;
|
||||
}"#,
|
||||
r#"
|
||||
vec![
|
||||
r#"
|
||||
struct Bar {}
|
||||
trait Foo {
|
||||
type Res;
|
||||
|
|
@ -337,6 +342,21 @@ fn main() {
|
|||
let a: i32 = 1;
|
||||
let c: Bar = Bar { };
|
||||
}"#,
|
||||
r#"
|
||||
struct Bar {}
|
||||
trait Foo {
|
||||
type Res;
|
||||
fn foo(&self) -> Self::Res;
|
||||
}
|
||||
impl Foo for i32 {
|
||||
type Res = Self;
|
||||
fn foo(&self) -> Self::Res { 1 }
|
||||
}
|
||||
fn main() {
|
||||
let a: i32 = 1;
|
||||
let c: Bar = todo!();
|
||||
}"#,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ use hir::{
|
|||
};
|
||||
use ide_db::{
|
||||
EditionedFileId, FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, Severity, SnippetCap,
|
||||
assists::{Assist, AssistId, AssistResolveStrategy},
|
||||
assists::{Assist, AssistId, AssistResolveStrategy, ExprFillDefaultMode},
|
||||
base_db::{ReleaseChannel, RootQueryDb as _},
|
||||
generated::lints::{CLIPPY_LINT_GROUPS, DEFAULT_LINT_GROUPS, DEFAULT_LINTS, Lint, LintGroup},
|
||||
imports::insert_use::InsertUseConfig,
|
||||
|
|
@ -219,17 +219,6 @@ impl Diagnostic {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ExprFillDefaultMode {
|
||||
Todo,
|
||||
Default,
|
||||
}
|
||||
impl Default for ExprFillDefaultMode {
|
||||
fn default() -> Self {
|
||||
Self::Todo
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DiagnosticsConfig {
|
||||
/// Whether native diagnostics are enabled.
|
||||
|
|
|
|||
|
|
@ -3,14 +3,16 @@
|
|||
mod overly_long_real_world_cases;
|
||||
|
||||
use ide_db::{
|
||||
LineIndexDatabase, RootDatabase, assists::AssistResolveStrategy, base_db::SourceDatabase,
|
||||
LineIndexDatabase, RootDatabase,
|
||||
assists::{AssistResolveStrategy, ExprFillDefaultMode},
|
||||
base_db::SourceDatabase,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use stdx::trim_indent;
|
||||
use test_fixture::WithFixture;
|
||||
use test_utils::{MiniCore, assert_eq_text, extract_annotations};
|
||||
|
||||
use crate::{DiagnosticsConfig, ExprFillDefaultMode, Severity};
|
||||
use crate::{DiagnosticsConfig, Severity};
|
||||
|
||||
/// Takes a multi-file input fixture with annotated cursor positions,
|
||||
/// and checks that:
|
||||
|
|
@ -160,55 +162,6 @@ pub(crate) fn check_has_fix(
|
|||
assert!(fix.is_some(), "no diagnostic with desired fix");
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub(crate) fn check_has_single_fix(
|
||||
#[rust_analyzer::rust_fixture] ra_fixture_before: &str,
|
||||
#[rust_analyzer::rust_fixture] ra_fixture_after: &str,
|
||||
) {
|
||||
let after = trim_indent(ra_fixture_after);
|
||||
|
||||
let (db, file_position) = RootDatabase::with_position(ra_fixture_before);
|
||||
let mut conf = DiagnosticsConfig::test_sample();
|
||||
conf.expr_fill_default = ExprFillDefaultMode::Default;
|
||||
let mut n_fixes = 0;
|
||||
let fix = super::full_diagnostics(
|
||||
&db,
|
||||
&conf,
|
||||
&AssistResolveStrategy::All,
|
||||
file_position.file_id.file_id(&db),
|
||||
)
|
||||
.into_iter()
|
||||
.find(|d| {
|
||||
d.fixes
|
||||
.as_ref()
|
||||
.and_then(|fixes| {
|
||||
n_fixes += fixes.len();
|
||||
fixes.iter().find(|fix| {
|
||||
if !fix.target.contains_inclusive(file_position.offset) {
|
||||
return false;
|
||||
}
|
||||
let actual = {
|
||||
let source_change = fix.source_change.as_ref().unwrap();
|
||||
let file_id = *source_change.source_file_edits.keys().next().unwrap();
|
||||
let mut actual = db.file_text(file_id).text(&db).to_string();
|
||||
|
||||
for (edit, snippet_edit) in source_change.source_file_edits.values() {
|
||||
edit.apply(&mut actual);
|
||||
if let Some(snippet_edit) = snippet_edit {
|
||||
snippet_edit.apply(&mut actual);
|
||||
}
|
||||
}
|
||||
actual
|
||||
};
|
||||
after == actual
|
||||
})
|
||||
})
|
||||
.is_some()
|
||||
});
|
||||
assert!(fix.is_some(), "no diagnostic with desired fix");
|
||||
assert!(n_fixes == 1, "Too many fixes suggested");
|
||||
}
|
||||
|
||||
/// Checks that there's a diagnostic *without* fix at `$0`.
|
||||
pub(crate) fn check_no_fix(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
||||
let (db, file_position) = RootDatabase::with_position(ra_fixture);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue