mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
internal: scalable module structure for fixits
This commit is contained in:
parent
db8fbb99ce
commit
fa7fc0e5cb
9 changed files with 695 additions and 769 deletions
|
@ -375,7 +375,7 @@ mod tests {
|
|||
assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics);
|
||||
}
|
||||
|
||||
fn check_expect(ra_fixture: &str, expect: Expect) {
|
||||
pub(crate) fn check_expect(ra_fixture: &str, expect: Expect) {
|
||||
let (analysis, file_id) = fixture::file(ra_fixture);
|
||||
let diagnostics = analysis
|
||||
.diagnostics(&DiagnosticsConfig::default(), AssistResolveStrategy::All, file_id)
|
||||
|
@ -383,374 +383,6 @@ mod tests {
|
|||
expect.assert_debug_eq(&diagnostics)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wrap_return_type_option() {
|
||||
check_fix(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
use core::option::Option::{self, Some, None};
|
||||
|
||||
fn div(x: i32, y: i32) -> Option<i32> {
|
||||
if y == 0 {
|
||||
return None;
|
||||
}
|
||||
x / y$0
|
||||
}
|
||||
//- /core/lib.rs crate:core
|
||||
pub mod result {
|
||||
pub enum Result<T, E> { Ok(T), Err(E) }
|
||||
}
|
||||
pub mod option {
|
||||
pub enum Option<T> { Some(T), None }
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
use core::option::Option::{self, Some, None};
|
||||
|
||||
fn div(x: i32, y: i32) -> Option<i32> {
|
||||
if y == 0 {
|
||||
return None;
|
||||
}
|
||||
Some(x / y)
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wrap_return_type() {
|
||||
check_fix(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
use core::result::Result::{self, Ok, Err};
|
||||
|
||||
fn div(x: i32, y: i32) -> Result<i32, ()> {
|
||||
if y == 0 {
|
||||
return Err(());
|
||||
}
|
||||
x / y$0
|
||||
}
|
||||
//- /core/lib.rs crate:core
|
||||
pub mod result {
|
||||
pub enum Result<T, E> { Ok(T), Err(E) }
|
||||
}
|
||||
pub mod option {
|
||||
pub enum Option<T> { Some(T), None }
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
use core::result::Result::{self, Ok, Err};
|
||||
|
||||
fn div(x: i32, y: i32) -> Result<i32, ()> {
|
||||
if y == 0 {
|
||||
return Err(());
|
||||
}
|
||||
Ok(x / y)
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wrap_return_type_handles_generic_functions() {
|
||||
check_fix(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
use core::result::Result::{self, Ok, Err};
|
||||
|
||||
fn div<T>(x: T) -> Result<T, i32> {
|
||||
if x == 0 {
|
||||
return Err(7);
|
||||
}
|
||||
$0x
|
||||
}
|
||||
//- /core/lib.rs crate:core
|
||||
pub mod result {
|
||||
pub enum Result<T, E> { Ok(T), Err(E) }
|
||||
}
|
||||
pub mod option {
|
||||
pub enum Option<T> { Some(T), None }
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
use core::result::Result::{self, Ok, Err};
|
||||
|
||||
fn div<T>(x: T) -> Result<T, i32> {
|
||||
if x == 0 {
|
||||
return Err(7);
|
||||
}
|
||||
Ok(x)
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wrap_return_type_handles_type_aliases() {
|
||||
check_fix(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
use core::result::Result::{self, Ok, Err};
|
||||
|
||||
type MyResult<T> = Result<T, ()>;
|
||||
|
||||
fn div(x: i32, y: i32) -> MyResult<i32> {
|
||||
if y == 0 {
|
||||
return Err(());
|
||||
}
|
||||
x $0/ y
|
||||
}
|
||||
//- /core/lib.rs crate:core
|
||||
pub mod result {
|
||||
pub enum Result<T, E> { Ok(T), Err(E) }
|
||||
}
|
||||
pub mod option {
|
||||
pub enum Option<T> { Some(T), None }
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
use core::result::Result::{self, Ok, Err};
|
||||
|
||||
type MyResult<T> = Result<T, ()>;
|
||||
|
||||
fn div(x: i32, y: i32) -> MyResult<i32> {
|
||||
if y == 0 {
|
||||
return Err(());
|
||||
}
|
||||
Ok(x / y)
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
|
||||
check_no_diagnostics(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
use core::result::Result::{self, Ok, Err};
|
||||
|
||||
fn foo() -> Result<(), i32> { 0 }
|
||||
|
||||
//- /core/lib.rs crate:core
|
||||
pub mod result {
|
||||
pub enum Result<T, E> { Ok(T), Err(E) }
|
||||
}
|
||||
pub mod option {
|
||||
pub enum Option<T> { Some(T), None }
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wrap_return_type_not_applicable_when_return_type_is_not_result_or_option() {
|
||||
check_no_diagnostics(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
use core::result::Result::{self, Ok, Err};
|
||||
|
||||
enum SomeOtherEnum { Ok(i32), Err(String) }
|
||||
|
||||
fn foo() -> SomeOtherEnum { 0 }
|
||||
|
||||
//- /core/lib.rs crate:core
|
||||
pub mod result {
|
||||
pub enum Result<T, E> { Ok(T), Err(E) }
|
||||
}
|
||||
pub mod option {
|
||||
pub enum Option<T> { Some(T), None }
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_struct_fields_empty() {
|
||||
check_fix(
|
||||
r#"
|
||||
struct TestStruct { one: i32, two: i64 }
|
||||
|
||||
fn test_fn() {
|
||||
let s = TestStruct {$0};
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct TestStruct { one: i32, two: i64 }
|
||||
|
||||
fn test_fn() {
|
||||
let s = TestStruct { one: (), two: () };
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_struct_fields_self() {
|
||||
check_fix(
|
||||
r#"
|
||||
struct TestStruct { one: i32 }
|
||||
|
||||
impl TestStruct {
|
||||
fn test_fn() { let s = Self {$0}; }
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct TestStruct { one: i32 }
|
||||
|
||||
impl TestStruct {
|
||||
fn test_fn() { let s = Self { one: () }; }
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_struct_fields_enum() {
|
||||
check_fix(
|
||||
r#"
|
||||
enum Expr {
|
||||
Bin { lhs: Box<Expr>, rhs: Box<Expr> }
|
||||
}
|
||||
|
||||
impl Expr {
|
||||
fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
|
||||
Expr::Bin {$0 }
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
enum Expr {
|
||||
Bin { lhs: Box<Expr>, rhs: Box<Expr> }
|
||||
}
|
||||
|
||||
impl Expr {
|
||||
fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
|
||||
Expr::Bin { lhs: (), rhs: () }
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_struct_fields_partial() {
|
||||
check_fix(
|
||||
r#"
|
||||
struct TestStruct { one: i32, two: i64 }
|
||||
|
||||
fn test_fn() {
|
||||
let s = TestStruct{ two: 2$0 };
|
||||
}
|
||||
"#,
|
||||
r"
|
||||
struct TestStruct { one: i32, two: i64 }
|
||||
|
||||
fn test_fn() {
|
||||
let s = TestStruct{ two: 2, one: () };
|
||||
}
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_struct_fields_raw_ident() {
|
||||
check_fix(
|
||||
r#"
|
||||
struct TestStruct { r#type: u8 }
|
||||
|
||||
fn test_fn() {
|
||||
TestStruct { $0 };
|
||||
}
|
||||
"#,
|
||||
r"
|
||||
struct TestStruct { r#type: u8 }
|
||||
|
||||
fn test_fn() {
|
||||
TestStruct { r#type: () };
|
||||
}
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_struct_fields_no_diagnostic() {
|
||||
check_no_diagnostics(
|
||||
r"
|
||||
struct TestStruct { one: i32, two: i64 }
|
||||
|
||||
fn test_fn() {
|
||||
let one = 1;
|
||||
let s = TestStruct{ one, two: 2 };
|
||||
}
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_struct_fields_no_diagnostic_on_spread() {
|
||||
check_no_diagnostics(
|
||||
r"
|
||||
struct TestStruct { one: i32, two: i64 }
|
||||
|
||||
fn test_fn() {
|
||||
let one = 1;
|
||||
let s = TestStruct{ ..a };
|
||||
}
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unresolved_module_diagnostic() {
|
||||
check_expect(
|
||||
r#"mod foo;"#,
|
||||
expect![[r#"
|
||||
[
|
||||
Diagnostic {
|
||||
message: "unresolved module",
|
||||
range: 0..8,
|
||||
severity: Error,
|
||||
fix: Some(
|
||||
Assist {
|
||||
id: AssistId(
|
||||
"create_module",
|
||||
QuickFix,
|
||||
),
|
||||
label: "Create module",
|
||||
group: None,
|
||||
target: 0..8,
|
||||
source_change: Some(
|
||||
SourceChange {
|
||||
source_file_edits: {},
|
||||
file_system_edits: [
|
||||
CreateFile {
|
||||
dst: AnchoredPathBuf {
|
||||
anchor: FileId(
|
||||
0,
|
||||
),
|
||||
path: "foo.rs",
|
||||
},
|
||||
initial_contents: "",
|
||||
},
|
||||
],
|
||||
is_snippet: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
unused: false,
|
||||
code: Some(
|
||||
DiagnosticCode(
|
||||
"unresolved-module",
|
||||
),
|
||||
),
|
||||
},
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unresolved_macro_range() {
|
||||
check_expect(
|
||||
|
@ -890,53 +522,6 @@ mod a {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_field_from_usage() {
|
||||
check_fix(
|
||||
r"
|
||||
fn main() {
|
||||
Foo { bar: 3, baz$0: false};
|
||||
}
|
||||
struct Foo {
|
||||
bar: i32
|
||||
}
|
||||
",
|
||||
r"
|
||||
fn main() {
|
||||
Foo { bar: 3, baz: false};
|
||||
}
|
||||
struct Foo {
|
||||
bar: i32,
|
||||
baz: bool
|
||||
}
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_field_in_other_file_from_usage() {
|
||||
check_fix(
|
||||
r#"
|
||||
//- /main.rs
|
||||
mod foo;
|
||||
|
||||
fn main() {
|
||||
foo::Foo { bar: 3, $0baz: false};
|
||||
}
|
||||
//- /foo.rs
|
||||
struct Foo {
|
||||
bar: i32
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct Foo {
|
||||
bar: i32,
|
||||
pub(crate) baz: bool
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_disabled_diagnostics() {
|
||||
let mut config = DiagnosticsConfig::default();
|
||||
|
@ -954,120 +539,6 @@ struct Foo {
|
|||
assert!(!diagnostics.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rename_incorrect_case() {
|
||||
check_fix(
|
||||
r#"
|
||||
pub struct test_struct$0 { one: i32 }
|
||||
|
||||
pub fn some_fn(val: test_struct) -> test_struct {
|
||||
test_struct { one: val.one + 1 }
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
pub struct TestStruct { one: i32 }
|
||||
|
||||
pub fn some_fn(val: TestStruct) -> TestStruct {
|
||||
TestStruct { one: val.one + 1 }
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_fix(
|
||||
r#"
|
||||
pub fn some_fn(NonSnakeCase$0: u8) -> u8 {
|
||||
NonSnakeCase
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
pub fn some_fn(non_snake_case: u8) -> u8 {
|
||||
non_snake_case
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_fix(
|
||||
r#"
|
||||
pub fn SomeFn$0(val: u8) -> u8 {
|
||||
if val != 0 { SomeFn(val - 1) } else { val }
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
pub fn some_fn(val: u8) -> u8 {
|
||||
if val != 0 { some_fn(val - 1) } else { val }
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_fix(
|
||||
r#"
|
||||
fn some_fn() {
|
||||
let whatAWeird_Formatting$0 = 10;
|
||||
another_func(whatAWeird_Formatting);
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn some_fn() {
|
||||
let what_a_weird_formatting = 10;
|
||||
another_func(what_a_weird_formatting);
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_uppercase_const_no_diagnostics() {
|
||||
check_no_diagnostics(
|
||||
r#"
|
||||
fn foo() {
|
||||
const ANOTHER_ITEM$0: &str = "some_item";
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rename_incorrect_case_struct_method() {
|
||||
check_fix(
|
||||
r#"
|
||||
pub struct TestStruct;
|
||||
|
||||
impl TestStruct {
|
||||
pub fn SomeFn$0() -> TestStruct {
|
||||
TestStruct
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
pub struct TestStruct;
|
||||
|
||||
impl TestStruct {
|
||||
pub fn some_fn() -> TestStruct {
|
||||
TestStruct
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_single_incorrect_case_diagnostic_in_function_name_issue_6970() {
|
||||
let input = r#"fn FOO$0() {}"#;
|
||||
let expected = r#"fn foo() {}"#;
|
||||
|
||||
let (analysis, file_position) = fixture::position(input);
|
||||
let diagnostics = analysis
|
||||
.diagnostics(
|
||||
&DiagnosticsConfig::default(),
|
||||
AssistResolveStrategy::All,
|
||||
file_position.file_id,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(diagnostics.len(), 1);
|
||||
|
||||
check_fix(input, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unlinked_file_prepend_first_item() {
|
||||
cov_mark::check!(unlinked_file_prepend_before_first_item);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue