More principled indentation trimming in fixtures

This commit is contained in:
Aleksey Kladov 2020-06-23 22:27:24 +02:00
parent f2f69e75c8
commit aa69757a01
16 changed files with 540 additions and 557 deletions

View file

@ -986,7 +986,6 @@ fn main() {
", ",
r" r"
pub(crate) fn bar() { pub(crate) fn bar() {
${0:todo!()} ${0:todo!()}
}", }",

View file

@ -488,16 +488,17 @@ mod tests {
check_assist( check_assist(
auto_import, auto_import,
r" r"
//- /lib.rs crate:crate_with_macro //- /lib.rs crate:crate_with_macro
#[macro_export] #[macro_export]
macro_rules! foo { macro_rules! foo {
() => () () => ()
} }
//- /main.rs crate:main deps:crate_with_macro //- /main.rs crate:main deps:crate_with_macro
fn main() { fn main() {
foo<|> foo<|>
}", }
",
r"use crate_with_macro::foo; r"use crate_with_macro::foo;
fn main() { fn main() {
@ -847,13 +848,14 @@ fn main() {
check_assist( check_assist(
auto_import, auto_import,
r" r"
//- /lib.rs crate:dep //- /lib.rs crate:dep
pub struct Struct; pub struct Struct;
//- /main.rs crate:main deps:dep //- /main.rs crate:main deps:dep
fn main() { fn main() {
Struct<|> Struct<|>
}", }
",
r"use dep::Struct; r"use dep::Struct;
fn main() { fn main() {
@ -869,20 +871,22 @@ fn main() {
check_assist( check_assist(
auto_import, auto_import,
r" r"
//- /lib.rs crate:dep //- /lib.rs crate:dep
pub mod fmt { pub mod fmt {
pub trait Display {} pub trait Display {}
} }
pub fn panic_fmt() {} pub fn panic_fmt() {}
//- /main.rs crate:main deps:dep //- /main.rs crate:main deps:dep
struct S; struct S;
impl f<|>mt::Display for S {}", impl f<|>mt::Display for S {}
",
r"use dep::fmt; r"use dep::fmt;
struct S; struct S;
impl fmt::Display for S {} impl fmt::Display for S {}
", ",
); );
@ -894,21 +898,20 @@ impl fmt::Display for S {}
check_assist( check_assist(
auto_import, auto_import,
r" r"
//- /lib.rs crate:dep //- /lib.rs crate:dep
macro_rules! mac {
() => {
pub struct Cheese;
};
}
macro_rules! mac { mac!();
() => {
pub struct Cheese;
};
}
mac!(); //- /main.rs crate:main deps:dep
fn main() {
//- /main.rs crate:main deps:dep Cheese<|>;
}
fn main() { ",
Cheese<|>;
}",
r"use dep::Cheese; r"use dep::Cheese;
fn main() { fn main() {
@ -924,16 +927,15 @@ fn main() {
check_assist( check_assist(
auto_import, auto_import,
r" r"
//- /lib.rs crate:dep //- /lib.rs crate:dep
pub struct FMT;
pub struct fmt;
pub struct FMT; //- /main.rs crate:main deps:dep
pub struct fmt; fn main() {
FMT<|>;
//- /main.rs crate:main deps:dep }
",
fn main() {
FMT<|>;
}",
r"use dep::FMT; r"use dep::FMT;
fn main() { fn main() {

View file

@ -255,15 +255,14 @@ mod tests {
check_assist( check_assist(
fix_visibility, fix_visibility,
r" r"
//- /main.rs //- /main.rs
mod foo; mod foo;
fn main() { foo::Foo<|> } fn main() { foo::Foo<|> }
//- /foo.rs //- /foo.rs
struct Foo; struct Foo;
", ",
r"$0pub(crate) struct Foo; r"$0pub(crate) struct Foo;
", ",
); );
} }
@ -279,14 +278,14 @@ mod tests {
); );
check_assist( check_assist(
fix_visibility, fix_visibility,
r"//- /lib.rs r"
mod foo; //- /lib.rs
fn main() { foo::Foo { <|>bar: () }; } mod foo;
//- /foo.rs fn main() { foo::Foo { <|>bar: () }; }
pub struct Foo { bar: () } //- /foo.rs
", pub struct Foo { bar: () }
",
r"pub struct Foo { $0pub(crate) bar: () } r"pub struct Foo { $0pub(crate) bar: () }
", ",
); );
check_assist_not_applicable( check_assist_not_applicable(
@ -296,12 +295,13 @@ mod tests {
); );
check_assist_not_applicable( check_assist_not_applicable(
fix_visibility, fix_visibility,
r"//- /lib.rs r"
mod foo; //- /lib.rs
fn main() { foo::Foo { <|>bar: () }; } mod foo;
//- /foo.rs fn main() { foo::Foo { <|>bar: () }; }
pub struct Foo { pub bar: () } //- /foo.rs
", pub struct Foo { pub bar: () }
",
); );
} }
@ -316,14 +316,14 @@ mod tests {
); );
check_assist( check_assist(
fix_visibility, fix_visibility,
r"//- /lib.rs r"
mod foo; //- /lib.rs
fn main() { foo::Foo::Bar { <|>bar: () }; } mod foo;
//- /foo.rs fn main() { foo::Foo::Bar { <|>bar: () }; }
pub enum Foo { Bar { bar: () } } //- /foo.rs
", pub enum Foo { Bar { bar: () } }
",
r"pub enum Foo { Bar { $0pub(crate) bar: () } } r"pub enum Foo { Bar { $0pub(crate) bar: () } }
", ",
); );
check_assist_not_applicable( check_assist_not_applicable(
@ -333,12 +333,13 @@ mod tests {
); );
check_assist_not_applicable( check_assist_not_applicable(
fix_visibility, fix_visibility,
r"//- /lib.rs r"
mod foo; //- /lib.rs
fn main() { foo::Foo { <|>bar: () }; } mod foo;
//- /foo.rs fn main() { foo::Foo { <|>bar: () }; }
pub struct Foo { pub bar: () } //- /foo.rs
", pub struct Foo { pub bar: () }
",
); );
} }
@ -355,14 +356,14 @@ mod tests {
); );
check_assist( check_assist(
fix_visibility, fix_visibility,
r"//- /lib.rs r"
mod foo; //- /lib.rs
fn main() { foo::Foo { <|>bar: () }; } mod foo;
//- /foo.rs fn main() { foo::Foo { <|>bar: () }; }
pub union Foo { bar: () } //- /foo.rs
", pub union Foo { bar: () }
",
r"pub union Foo { $0pub(crate) bar: () } r"pub union Foo { $0pub(crate) bar: () }
", ",
); );
check_assist_not_applicable( check_assist_not_applicable(
@ -372,12 +373,13 @@ mod tests {
); );
check_assist_not_applicable( check_assist_not_applicable(
fix_visibility, fix_visibility,
r"//- /lib.rs r"
mod foo; //- /lib.rs
fn main() { foo::Foo { <|>bar: () }; } mod foo;
//- /foo.rs fn main() { foo::Foo { <|>bar: () }; }
pub union Foo { pub bar: () } //- /foo.rs
", pub union Foo { pub bar: () }
",
); );
} }
@ -458,19 +460,18 @@ mod tests {
check_assist( check_assist(
fix_visibility, fix_visibility,
r" r"
//- /main.rs //- /main.rs
mod foo; mod foo;
fn main() { foo::bar<|>::baz(); } fn main() { foo::bar<|>::baz(); }
//- /foo.rs //- /foo.rs
mod bar { mod bar {
pub fn baz() {} pub fn baz() {}
} }
", ",
r"$0pub(crate) mod bar { r"$0pub(crate) mod bar {
pub fn baz() {} pub fn baz() {}
} }
", ",
); );
@ -486,17 +487,15 @@ mod tests {
check_assist( check_assist(
fix_visibility, fix_visibility,
r" r"
//- /main.rs //- /main.rs
mod foo; mod foo;
fn main() { foo::bar<|>::baz(); } fn main() { foo::bar<|>::baz(); }
//- /foo.rs //- /foo.rs
mod bar; mod bar;
//- /foo/bar.rs
//- /foo/bar.rs pub fn baz() {}
pub fn baz() {} ",
}
",
r"$0pub(crate) mod bar; r"$0pub(crate) mod bar;
", ",
); );
@ -506,14 +505,16 @@ mod tests {
fn fix_visibility_of_module_declaration_in_other_file() { fn fix_visibility_of_module_declaration_in_other_file() {
check_assist( check_assist(
fix_visibility, fix_visibility,
r"//- /main.rs r"
mod foo; //- /main.rs
fn main() { foo::bar<|>>::baz(); } mod foo;
fn main() { foo::bar<|>>::baz(); }
//- /foo.rs //- /foo.rs
mod bar { mod bar {
pub fn baz() {} pub fn baz() {}
}", }
",
r"$0pub(crate) mod bar { r"$0pub(crate) mod bar {
pub fn baz() {} pub fn baz() {}
} }
@ -525,10 +526,12 @@ mod tests {
fn adds_pub_when_target_is_in_another_crate() { fn adds_pub_when_target_is_in_another_crate() {
check_assist( check_assist(
fix_visibility, fix_visibility,
r"//- /main.rs crate:a deps:foo r"
foo::Bar<|> //- /main.rs crate:a deps:foo
//- /lib.rs crate:foo foo::Bar<|>
struct Bar;", //- /lib.rs crate:foo
struct Bar;
",
r"$0pub struct Bar; r"$0pub struct Bar;
", ",
) )

View file

@ -145,12 +145,12 @@ mod tests {
use crate::mock_analysis::analysis_and_position; use crate::mock_analysis::analysis_and_position;
fn check_hierarchy( fn check_hierarchy(
fixture: &str, ra_fixture: &str,
expected: &str, expected: &str,
expected_incoming: &[&str], expected_incoming: &[&str],
expected_outgoing: &[&str], expected_outgoing: &[&str],
) { ) {
let (analysis, pos) = analysis_and_position(fixture); let (analysis, pos) = analysis_and_position(ra_fixture);
let mut navs = analysis.call_hierarchy(pos).unwrap().unwrap().info; let mut navs = analysis.call_hierarchy(pos).unwrap().unwrap().info;
assert_eq!(navs.len(), 1); assert_eq!(navs.len(), 1);
@ -177,12 +177,12 @@ mod tests {
fn test_call_hierarchy_on_ref() { fn test_call_hierarchy_on_ref() {
check_hierarchy( check_hierarchy(
r#" r#"
//- /lib.rs //- /lib.rs
fn callee() {} fn callee() {}
fn caller() { fn caller() {
call<|>ee(); call<|>ee();
} }
"#, "#,
"callee FN_DEF FileId(1) 0..14 3..9", "callee FN_DEF FileId(1) 0..14 3..9",
&["caller FN_DEF FileId(1) 15..44 18..24 : [33..39]"], &["caller FN_DEF FileId(1) 15..44 18..24 : [33..39]"],
&[], &[],
@ -193,12 +193,12 @@ mod tests {
fn test_call_hierarchy_on_def() { fn test_call_hierarchy_on_def() {
check_hierarchy( check_hierarchy(
r#" r#"
//- /lib.rs //- /lib.rs
fn call<|>ee() {} fn call<|>ee() {}
fn caller() { fn caller() {
callee(); callee();
} }
"#, "#,
"callee FN_DEF FileId(1) 0..14 3..9", "callee FN_DEF FileId(1) 0..14 3..9",
&["caller FN_DEF FileId(1) 15..44 18..24 : [33..39]"], &["caller FN_DEF FileId(1) 15..44 18..24 : [33..39]"],
&[], &[],
@ -209,13 +209,13 @@ mod tests {
fn test_call_hierarchy_in_same_fn() { fn test_call_hierarchy_in_same_fn() {
check_hierarchy( check_hierarchy(
r#" r#"
//- /lib.rs //- /lib.rs
fn callee() {} fn callee() {}
fn caller() { fn caller() {
call<|>ee(); call<|>ee();
callee(); callee();
} }
"#, "#,
"callee FN_DEF FileId(1) 0..14 3..9", "callee FN_DEF FileId(1) 0..14 3..9",
&["caller FN_DEF FileId(1) 15..58 18..24 : [33..39, 47..53]"], &["caller FN_DEF FileId(1) 15..58 18..24 : [33..39, 47..53]"],
&[], &[],
@ -226,20 +226,20 @@ mod tests {
fn test_call_hierarchy_in_different_fn() { fn test_call_hierarchy_in_different_fn() {
check_hierarchy( check_hierarchy(
r#" r#"
//- /lib.rs //- /lib.rs
fn callee() {} fn callee() {}
fn caller1() { fn caller1() {
call<|>ee(); call<|>ee();
} }
fn caller2() { fn caller2() {
callee(); callee();
} }
"#, "#,
"callee FN_DEF FileId(1) 0..14 3..9", "callee FN_DEF FileId(1) 0..14 3..9",
&[ &[
"caller1 FN_DEF FileId(1) 15..45 18..25 : [34..40]", "caller1 FN_DEF FileId(1) 15..45 18..25 : [34..40]",
"caller2 FN_DEF FileId(1) 46..76 49..56 : [65..71]", "caller2 FN_DEF FileId(1) 47..77 50..57 : [66..72]",
], ],
&[], &[],
); );
@ -249,26 +249,26 @@ mod tests {
fn test_call_hierarchy_in_tests_mod() { fn test_call_hierarchy_in_tests_mod() {
check_hierarchy( check_hierarchy(
r#" r#"
//- /lib.rs cfg:test //- /lib.rs cfg:test
fn callee() {} fn callee() {}
fn caller1() { fn caller1() {
call<|>ee(); call<|>ee();
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
#[test] #[test]
fn test_caller() { fn test_caller() {
callee(); callee();
} }
} }
"#, "#,
"callee FN_DEF FileId(1) 0..14 3..9", "callee FN_DEF FileId(1) 0..14 3..9",
&[ &[
"caller1 FN_DEF FileId(1) 15..45 18..25 : [34..40]", "caller1 FN_DEF FileId(1) 15..45 18..25 : [34..40]",
"test_caller FN_DEF FileId(1) 93..147 108..119 : [132..138]", "test_caller FN_DEF FileId(1) 95..149 110..121 : [134..140]",
], ],
&[], &[],
); );
@ -278,19 +278,19 @@ mod tests {
fn test_call_hierarchy_in_different_files() { fn test_call_hierarchy_in_different_files() {
check_hierarchy( check_hierarchy(
r#" r#"
//- /lib.rs //- /lib.rs
mod foo; mod foo;
use foo::callee; use foo::callee;
fn caller() { fn caller() {
call<|>ee(); call<|>ee();
} }
//- /foo/mod.rs //- /foo/mod.rs
pub fn callee() {} pub fn callee() {}
"#, "#,
"callee FN_DEF FileId(2) 0..18 7..13", "callee FN_DEF FileId(2) 0..18 7..13",
&["caller FN_DEF FileId(1) 26..55 29..35 : [44..50]"], &["caller FN_DEF FileId(1) 27..56 30..36 : [45..51]"],
&[], &[],
); );
} }
@ -299,13 +299,13 @@ mod tests {
fn test_call_hierarchy_outgoing() { fn test_call_hierarchy_outgoing() {
check_hierarchy( check_hierarchy(
r#" r#"
//- /lib.rs //- /lib.rs
fn callee() {} fn callee() {}
fn call<|>er() { fn call<|>er() {
callee(); callee();
callee(); callee();
} }
"#, "#,
"caller FN_DEF FileId(1) 15..58 18..24", "caller FN_DEF FileId(1) 15..58 18..24",
&[], &[],
&["callee FN_DEF FileId(1) 0..14 3..9 : [33..39, 47..53]"], &["callee FN_DEF FileId(1) 0..14 3..9 : [33..39, 47..53]"],
@ -316,20 +316,20 @@ mod tests {
fn test_call_hierarchy_outgoing_in_different_files() { fn test_call_hierarchy_outgoing_in_different_files() {
check_hierarchy( check_hierarchy(
r#" r#"
//- /lib.rs //- /lib.rs
mod foo; mod foo;
use foo::callee; use foo::callee;
fn call<|>er() { fn call<|>er() {
callee(); callee();
} }
//- /foo/mod.rs //- /foo/mod.rs
pub fn callee() {} pub fn callee() {}
"#, "#,
"caller FN_DEF FileId(1) 26..55 29..35", "caller FN_DEF FileId(1) 27..56 30..36",
&[], &[],
&["callee FN_DEF FileId(2) 0..18 7..13 : [44..50]"], &["callee FN_DEF FileId(2) 0..18 7..13 : [45..51]"],
); );
} }
@ -337,22 +337,22 @@ mod tests {
fn test_call_hierarchy_incoming_outgoing() { fn test_call_hierarchy_incoming_outgoing() {
check_hierarchy( check_hierarchy(
r#" r#"
//- /lib.rs //- /lib.rs
fn caller1() { fn caller1() {
call<|>er2(); call<|>er2();
} }
fn caller2() { fn caller2() {
caller3(); caller3();
} }
fn caller3() { fn caller3() {
} }
"#, "#,
"caller2 FN_DEF FileId(1) 32..63 35..42", "caller2 FN_DEF FileId(1) 33..64 36..43",
&["caller1 FN_DEF FileId(1) 0..31 3..10 : [19..26]"], &["caller1 FN_DEF FileId(1) 0..31 3..10 : [19..26]"],
&["caller3 FN_DEF FileId(1) 64..80 67..74 : [51..58]"], &["caller3 FN_DEF FileId(1) 66..83 69..76 : [52..59]"],
); );
} }
} }

View file

@ -42,8 +42,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "foo!(…)", label: "foo!(…)",
source_range: 46..46, source_range: 48..48,
delete: 46..46, delete: 48..48,
insert: "foo!($0)", insert: "foo!($0)",
kind: Macro, kind: Macro,
detail: "macro_rules! foo", detail: "macro_rules! foo",
@ -82,8 +82,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "vec![…]", label: "vec![…]",
source_range: 280..280, source_range: 282..282,
delete: 280..280, delete: 282..282,
insert: "vec![$0]", insert: "vec![$0]",
kind: Macro, kind: Macro,
detail: "macro_rules! vec", detail: "macro_rules! vec",
@ -119,8 +119,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "foo! {…}", label: "foo! {…}",
source_range: 163..163, source_range: 164..164,
delete: 163..163, delete: 164..164,
insert: "foo! {$0}", insert: "foo! {$0}",
kind: Macro, kind: Macro,
detail: "macro_rules! foo", detail: "macro_rules! foo",
@ -130,8 +130,8 @@ mod tests {
}, },
CompletionItem { CompletionItem {
label: "main()", label: "main()",
source_range: 163..163, source_range: 164..164,
delete: 163..163, delete: 164..164,
insert: "main()$0", insert: "main()$0",
kind: Function, kind: Function,
lookup: "main", lookup: "main",

View file

@ -541,8 +541,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "m()", label: "m()",
source_range: 100..100, source_range: 102..102,
delete: 100..100, delete: 102..102,
insert: "m()$0", insert: "m()$0",
kind: Function, kind: Function,
lookup: "m", lookup: "m",
@ -577,8 +577,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "m()", label: "m()",
source_range: 105..105, source_range: 107..107,
delete: 105..105, delete: 107..107,
insert: "m()$0", insert: "m()$0",
kind: Method, kind: Method,
lookup: "m", lookup: "m",
@ -613,8 +613,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "C", label: "C",
source_range: 107..107, source_range: 109..109,
delete: 107..107, delete: 109..109,
insert: "C", insert: "C",
kind: Const, kind: Const,
detail: "const C: i32 = 42;", detail: "const C: i32 = 42;",
@ -648,8 +648,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "T", label: "T",
source_range: 101..101, source_range: 103..103,
delete: 101..101, delete: 103..103,
insert: "T", insert: "T",
kind: TypeAlias, kind: TypeAlias,
detail: "type T = i32;", detail: "type T = i32;",
@ -688,24 +688,24 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "PUBLIC_CONST", label: "PUBLIC_CONST",
source_range: 302..302, source_range: 304..304,
delete: 302..302, delete: 304..304,
insert: "PUBLIC_CONST", insert: "PUBLIC_CONST",
kind: Const, kind: Const,
detail: "pub(super) const PUBLIC_CONST: u32 = 1;", detail: "pub(super) const PUBLIC_CONST: u32 = 1;",
}, },
CompletionItem { CompletionItem {
label: "PublicType", label: "PublicType",
source_range: 302..302, source_range: 304..304,
delete: 302..302, delete: 304..304,
insert: "PublicType", insert: "PublicType",
kind: TypeAlias, kind: TypeAlias,
detail: "pub(super) type PublicType = u32;", detail: "pub(super) type PublicType = u32;",
}, },
CompletionItem { CompletionItem {
label: "public_method()", label: "public_method()",
source_range: 302..302, source_range: 304..304,
delete: 302..302, delete: 304..304,
insert: "public_method()$0", insert: "public_method()$0",
kind: Function, kind: Function,
lookup: "public_method", lookup: "public_method",
@ -737,8 +737,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "m()", label: "m()",
source_range: 100..100, source_range: 102..102,
delete: 100..100, delete: 102..102,
insert: "m()$0", insert: "m()$0",
kind: Function, kind: Function,
lookup: "m", lookup: "m",
@ -773,8 +773,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "m()", label: "m()",
source_range: 101..101, source_range: 103..103,
delete: 101..101, delete: 103..103,
insert: "m()$0", insert: "m()$0",
kind: Function, kind: Function,
lookup: "m", lookup: "m",
@ -834,8 +834,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "m()", label: "m()",
source_range: 73..73, source_range: 74..74,
delete: 73..73, delete: 74..74,
insert: "m()$0", insert: "m()$0",
kind: Function, kind: Function,
lookup: "m", lookup: "m",
@ -870,8 +870,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "m()", label: "m()",
source_range: 99..99, source_range: 101..101,
delete: 99..99, delete: 101..101,
insert: "m()$0", insert: "m()$0",
kind: Function, kind: Function,
lookup: "m", lookup: "m",
@ -906,8 +906,8 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "m()", label: "m()",
source_range: 110..110, source_range: 112..112,
delete: 110..110, delete: 112..112,
insert: "m()$0", insert: "m()$0",
kind: Function, kind: Function,
lookup: "m", lookup: "m",
@ -950,40 +950,40 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "C2", label: "C2",
source_range: 219..219, source_range: 221..221,
delete: 219..219, delete: 221..221,
insert: "C2", insert: "C2",
kind: Const, kind: Const,
detail: "const C2: ();", detail: "const C2: ();",
}, },
CompletionItem { CompletionItem {
label: "CONST", label: "CONST",
source_range: 219..219, source_range: 221..221,
delete: 219..219, delete: 221..221,
insert: "CONST", insert: "CONST",
kind: Const, kind: Const,
detail: "const CONST: u8;", detail: "const CONST: u8;",
}, },
CompletionItem { CompletionItem {
label: "SubTy", label: "SubTy",
source_range: 219..219, source_range: 221..221,
delete: 219..219, delete: 221..221,
insert: "SubTy", insert: "SubTy",
kind: TypeAlias, kind: TypeAlias,
detail: "type SubTy;", detail: "type SubTy;",
}, },
CompletionItem { CompletionItem {
label: "Ty", label: "Ty",
source_range: 219..219, source_range: 221..221,
delete: 219..219, delete: 221..221,
insert: "Ty", insert: "Ty",
kind: TypeAlias, kind: TypeAlias,
detail: "type Ty;", detail: "type Ty;",
}, },
CompletionItem { CompletionItem {
label: "func()", label: "func()",
source_range: 219..219, source_range: 221..221,
delete: 219..219, delete: 221..221,
insert: "func()$0", insert: "func()$0",
kind: Function, kind: Function,
lookup: "func", lookup: "func",
@ -991,8 +991,8 @@ mod tests {
}, },
CompletionItem { CompletionItem {
label: "method()", label: "method()",
source_range: 219..219, source_range: 221..221,
delete: 219..219, delete: 221..221,
insert: "method()$0", insert: "method()$0",
kind: Method, kind: Method,
lookup: "method", lookup: "method",
@ -1000,8 +1000,8 @@ mod tests {
}, },
CompletionItem { CompletionItem {
label: "subfunc()", label: "subfunc()",
source_range: 219..219, source_range: 221..221,
delete: 219..219, delete: 221..221,
insert: "subfunc()$0", insert: "subfunc()$0",
kind: Function, kind: Function,
lookup: "subfunc", lookup: "subfunc",
@ -1009,8 +1009,8 @@ mod tests {
}, },
CompletionItem { CompletionItem {
label: "submethod()", label: "submethod()",
source_range: 219..219, source_range: 221..221,
delete: 219..219, delete: 221..221,
insert: "submethod()$0", insert: "submethod()$0",
kind: Method, kind: Method,
lookup: "submethod", lookup: "submethod",
@ -1055,40 +1055,40 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "C2", label: "C2",
source_range: 365..365, source_range: 367..367,
delete: 365..365, delete: 367..367,
insert: "C2", insert: "C2",
kind: Const, kind: Const,
detail: "const C2: () = ();", detail: "const C2: () = ();",
}, },
CompletionItem { CompletionItem {
label: "CONST", label: "CONST",
source_range: 365..365, source_range: 367..367,
delete: 365..365, delete: 367..367,
insert: "CONST", insert: "CONST",
kind: Const, kind: Const,
detail: "const CONST: u8 = 0;", detail: "const CONST: u8 = 0;",
}, },
CompletionItem { CompletionItem {
label: "SubTy", label: "SubTy",
source_range: 365..365, source_range: 367..367,
delete: 365..365, delete: 367..367,
insert: "SubTy", insert: "SubTy",
kind: TypeAlias, kind: TypeAlias,
detail: "type SubTy;", detail: "type SubTy;",
}, },
CompletionItem { CompletionItem {
label: "Ty", label: "Ty",
source_range: 365..365, source_range: 367..367,
delete: 365..365, delete: 367..367,
insert: "Ty", insert: "Ty",
kind: TypeAlias, kind: TypeAlias,
detail: "type Ty;", detail: "type Ty;",
}, },
CompletionItem { CompletionItem {
label: "func()", label: "func()",
source_range: 365..365, source_range: 367..367,
delete: 365..365, delete: 367..367,
insert: "func()$0", insert: "func()$0",
kind: Function, kind: Function,
lookup: "func", lookup: "func",
@ -1096,8 +1096,8 @@ mod tests {
}, },
CompletionItem { CompletionItem {
label: "method()", label: "method()",
source_range: 365..365, source_range: 367..367,
delete: 365..365, delete: 367..367,
insert: "method()$0", insert: "method()$0",
kind: Method, kind: Method,
lookup: "method", lookup: "method",
@ -1105,8 +1105,8 @@ mod tests {
}, },
CompletionItem { CompletionItem {
label: "subfunc()", label: "subfunc()",
source_range: 365..365, source_range: 367..367,
delete: 365..365, delete: 367..367,
insert: "subfunc()$0", insert: "subfunc()$0",
kind: Function, kind: Function,
lookup: "subfunc", lookup: "subfunc",
@ -1114,8 +1114,8 @@ mod tests {
}, },
CompletionItem { CompletionItem {
label: "submethod()", label: "submethod()",
source_range: 365..365, source_range: 367..367,
delete: 365..365, delete: 367..367,
insert: "submethod()$0", insert: "submethod()$0",
kind: Method, kind: Method,
lookup: "submethod", lookup: "submethod",

View file

@ -781,46 +781,46 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "bar!(…)", label: "bar!(…)",
source_range: 252..252, source_range: 256..256,
delete: 252..252, delete: 256..256,
insert: "bar!($0)", insert: "bar!($0)",
kind: Macro, kind: Macro,
detail: "macro_rules! bar", detail: "macro_rules! bar",
}, },
CompletionItem { CompletionItem {
label: "baz!(…)", label: "baz!(…)",
source_range: 252..252, source_range: 256..256,
delete: 252..252, delete: 256..256,
insert: "baz!($0)", insert: "baz!($0)",
kind: Macro, kind: Macro,
detail: "#[macro_export]\nmacro_rules! baz", detail: "#[macro_export]\nmacro_rules! baz",
}, },
CompletionItem { CompletionItem {
label: "foo!(…)", label: "foo!(…)",
source_range: 252..252, source_range: 256..256,
delete: 252..252, delete: 256..256,
insert: "foo!($0)", insert: "foo!($0)",
kind: Macro, kind: Macro,
detail: "macro_rules! foo", detail: "macro_rules! foo",
}, },
CompletionItem { CompletionItem {
label: "m1", label: "m1",
source_range: 252..252, source_range: 256..256,
delete: 252..252, delete: 256..256,
insert: "m1", insert: "m1",
kind: Module, kind: Module,
}, },
CompletionItem { CompletionItem {
label: "m2", label: "m2",
source_range: 252..252, source_range: 256..256,
delete: 252..252, delete: 256..256,
insert: "m2", insert: "m2",
kind: Module, kind: Module,
}, },
CompletionItem { CompletionItem {
label: "main()", label: "main()",
source_range: 252..252, source_range: 256..256,
delete: 252..252, delete: 256..256,
insert: "main()$0", insert: "main()$0",
kind: Function, kind: Function,
lookup: "main", lookup: "main",
@ -850,16 +850,16 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "foo!(…)", label: "foo!(…)",
source_range: 49..49, source_range: 50..50,
delete: 49..49, delete: 50..50,
insert: "foo!($0)", insert: "foo!($0)",
kind: Macro, kind: Macro,
detail: "macro_rules! foo", detail: "macro_rules! foo",
}, },
CompletionItem { CompletionItem {
label: "foo()", label: "foo()",
source_range: 49..49, source_range: 50..50,
delete: 49..49, delete: 50..50,
insert: "foo()$0", insert: "foo()$0",
kind: Function, kind: Function,
lookup: "foo", lookup: "foo",
@ -889,16 +889,16 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "foo!(…)", label: "foo!(…)",
source_range: 57..57, source_range: 58..58,
delete: 57..57, delete: 58..58,
insert: "foo!($0)", insert: "foo!($0)",
kind: Macro, kind: Macro,
detail: "macro_rules! foo", detail: "macro_rules! foo",
}, },
CompletionItem { CompletionItem {
label: "main()", label: "main()",
source_range: 57..57, source_range: 58..58,
delete: 57..57, delete: 58..58,
insert: "main()$0", insert: "main()$0",
kind: Function, kind: Function,
lookup: "main", lookup: "main",
@ -928,16 +928,16 @@ mod tests {
[ [
CompletionItem { CompletionItem {
label: "foo!(…)", label: "foo!(…)",
source_range: 50..50, source_range: 51..51,
delete: 50..50, delete: 51..51,
insert: "foo!($0)", insert: "foo!($0)",
kind: Macro, kind: Macro,
detail: "macro_rules! foo", detail: "macro_rules! foo",
}, },
CompletionItem { CompletionItem {
label: "main()", label: "main()",
source_range: 50..50, source_range: 51..51,
delete: 50..50, delete: 51..51,
insert: "main()$0", insert: "main()$0",
kind: Function, kind: Function,
lookup: "main", lookup: "main",

View file

@ -283,7 +283,7 @@ fn check_struct_shorthand_initialization(
mod tests { mod tests {
use insta::assert_debug_snapshot; use insta::assert_debug_snapshot;
use ra_syntax::SourceFile; use ra_syntax::SourceFile;
use stdx::SepBy; use stdx::trim_indent;
use test_utils::assert_eq_text; use test_utils::assert_eq_text;
use crate::mock_analysis::{analysis_and_position, single_file}; use crate::mock_analysis::{analysis_and_position, single_file};
@ -325,6 +325,8 @@ mod tests {
/// * this diagnostic touches the input cursor position /// * this diagnostic touches the input cursor position
/// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied
fn check_apply_diagnostic_fix_from_position(fixture: &str, after: &str) { fn check_apply_diagnostic_fix_from_position(fixture: &str, after: &str) {
let after = trim_indent(after);
let (analysis, file_position) = analysis_and_position(fixture); let (analysis, file_position) = analysis_and_position(fixture);
let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap(); let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap();
let mut fix = diagnostic.fix.unwrap(); let mut fix = diagnostic.fix.unwrap();
@ -336,21 +338,6 @@ mod tests {
actual actual
}; };
// Strip indent and empty lines from `after`, to match the behaviour of
// `parse_fixture` called from `analysis_and_position`.
let margin = fixture
.lines()
.filter(|it| it.trim_start().starts_with("//-"))
.map(|it| it.len() - it.trim_start().len())
.next()
.expect("empty fixture");
let after = after
.lines()
.filter_map(|line| if line.len() > margin { Some(&line[margin..]) } else { None })
.sep_by("\n")
.suffix("\n")
.to_string();
assert_eq_text!(&after, &actual); assert_eq_text!(&after, &actual);
assert!( assert!(
diagnostic.range.start() <= file_position.offset diagnostic.range.start() <= file_position.offset
@ -400,7 +387,6 @@ mod tests {
} }
x / y<|> x / y<|>
} }
//- /core/lib.rs //- /core/lib.rs
pub mod result { pub mod result {
pub enum Result<T, E> { Ok(T), Err(E) } pub enum Result<T, E> { Ok(T), Err(E) }
@ -431,7 +417,6 @@ mod tests {
} }
<|>x <|>x
} }
//- /core/lib.rs //- /core/lib.rs
pub mod result { pub mod result {
pub enum Result<T, E> { Ok(T), Err(E) } pub enum Result<T, E> { Ok(T), Err(E) }
@ -464,7 +449,6 @@ mod tests {
} }
x <|>/ y x <|>/ y
} }
//- /core/lib.rs //- /core/lib.rs
pub mod result { pub mod result {
pub enum Result<T, E> { Ok(T), Err(E) } pub enum Result<T, E> { Ok(T), Err(E) }
@ -474,6 +458,7 @@ mod tests {
use core::result::Result::{self, Ok, Err}; use core::result::Result::{self, Ok, Err};
type MyResult<T> = Result<T, ()>; type MyResult<T> = Result<T, ()>;
fn div(x: i32, y: i32) -> MyResult<i32> { fn div(x: i32, y: i32) -> MyResult<i32> {
if y == 0 { if y == 0 {
return Err(()); return Err(());

View file

@ -192,27 +192,27 @@ mod tests {
#[test] #[test]
fn goto_def_for_module_declaration() { fn goto_def_for_module_declaration() {
check_goto( check_goto(
" r#"
//- /lib.rs //- /lib.rs
mod <|>foo; mod <|>foo;
//- /foo.rs //- /foo.rs
// empty // empty
", "#,
"foo SOURCE_FILE FileId(2) 0..10", "foo SOURCE_FILE FileId(2) 0..9",
"// empty\n\n", "// empty\n",
); );
check_goto( check_goto(
" r#"
//- /lib.rs //- /lib.rs
mod <|>foo; mod <|>foo;
//- /foo/mod.rs //- /foo/mod.rs
// empty // empty
", "#,
"foo SOURCE_FILE FileId(2) 0..10", "foo SOURCE_FILE FileId(2) 0..9",
"// empty\n\n", "// empty\n",
); );
} }
@ -254,14 +254,14 @@ mod tests {
#[test] #[test]
fn goto_def_for_use_alias() { fn goto_def_for_use_alias() {
check_goto( check_goto(
" r#"
//- /lib.rs //- /lib.rs
use foo as bar<|>; use foo as bar<|>;
//- /foo/lib.rs
//- /foo/lib.rs #[macro_export]
#[macro_export] macro_rules! foo { () => { () } }
macro_rules! foo { () => { () } }", "#,
"SOURCE_FILE FileId(2) 0..50", "SOURCE_FILE FileId(2) 0..50",
"#[macro_export]\nmacro_rules! foo { () => { () } }\n", "#[macro_export]\nmacro_rules! foo { () => { () } }\n",
); );
@ -302,19 +302,19 @@ mod tests {
#[test] #[test]
fn goto_def_for_macro_defined_fn_with_arg() { fn goto_def_for_macro_defined_fn_with_arg() {
check_goto( check_goto(
" r#"
//- /lib.rs //- /lib.rs
macro_rules! define_fn { macro_rules! define_fn {
($name:ident) => (fn $name() {}) ($name:ident) => (fn $name() {})
} }
define_fn!(foo); define_fn!(foo);
fn bar() { fn bar() {
<|>foo(); <|>foo();
} }
", "#,
"foo FN_DEF FileId(1) 64..80 75..78", "foo FN_DEF FileId(1) 65..81 76..79",
"define_fn!(foo);|foo", "define_fn!(foo);|foo",
); );
} }
@ -322,19 +322,19 @@ mod tests {
#[test] #[test]
fn goto_def_for_macro_defined_fn_no_arg() { fn goto_def_for_macro_defined_fn_no_arg() {
check_goto( check_goto(
" r#"
//- /lib.rs //- /lib.rs
macro_rules! define_fn { macro_rules! define_fn {
() => (fn foo() {}) () => (fn foo() {})
} }
define_fn!(); define_fn!();
fn bar() { fn bar() {
<|>foo(); <|>foo();
} }
", "#,
"foo FN_DEF FileId(1) 51..64 51..64", "foo FN_DEF FileId(1) 52..65 52..65",
"define_fn!();|define_fn!();", "define_fn!();|define_fn!();",
); );
} }
@ -804,40 +804,40 @@ mod tests {
#[test] #[test]
fn goto_within_macro() { fn goto_within_macro() {
check_goto( check_goto(
" r#"
//- /lib.rs //- /lib.rs
macro_rules! id { macro_rules! id {
($($tt:tt)*) => ($($tt)*) ($($tt:tt)*) => ($($tt)*)
} }
fn foo() { fn foo() {
let x = 1; let x = 1;
id!({ id!({
let y = <|>x; let y = <|>x;
let z = y; let z = y;
}); });
} }
", "#,
"x BIND_PAT FileId(1) 69..70", "x BIND_PAT FileId(1) 70..71",
"x", "x",
); );
check_goto( check_goto(
" r#"
//- /lib.rs //- /lib.rs
macro_rules! id { macro_rules! id {
($($tt:tt)*) => ($($tt)*) ($($tt:tt)*) => ($($tt)*)
} }
fn foo() { fn foo() {
let x = 1; let x = 1;
id!({ id!({
let y = x; let y = x;
let z = <|>y; let z = <|>y;
}); });
} }
", "#,
"y BIND_PAT FileId(1) 98..99", "y BIND_PAT FileId(1) 99..100",
"y", "y",
); );
} }

View file

@ -2106,51 +2106,51 @@ fn func(foo: i32) { if true { <|>foo; }; }
); );
assert_debug_snapshot!(actions, assert_debug_snapshot!(actions,
@r###" @r###"
[ [
GoToType( GoToType(
[ [
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "B", mod_path: "B",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 41..54, full_range: 42..55,
name: "B", name: "B",
kind: STRUCT_DEF, kind: STRUCT_DEF,
focus_range: Some( focus_range: Some(
48..49, 49..50,
), ),
container_name: None, container_name: None,
description: Some( description: Some(
"struct B", "struct B",
), ),
docs: None, docs: None,
},
}, },
HoverGotoTypeData { },
mod_path: "Foo", HoverGotoTypeData {
nav: NavigationTarget { mod_path: "Foo",
file_id: FileId( nav: NavigationTarget {
1, file_id: FileId(
), 1,
full_range: 0..12, ),
name: "Foo", full_range: 0..12,
kind: TRAIT_DEF, name: "Foo",
focus_range: Some( kind: TRAIT_DEF,
6..9, focus_range: Some(
), 6..9,
container_name: None, ),
description: Some( container_name: None,
"trait Foo", description: Some(
), "trait Foo",
docs: None, ),
}, docs: None,
}, },
], },
), ],
] ),
"###); ]
"###);
} }
#[test] #[test]

View file

@ -427,8 +427,8 @@ mod tests {
let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); let refs = analysis.find_all_refs(pos, None).unwrap().unwrap();
check_result( check_result(
refs, refs,
"Foo STRUCT_DEF FileId(2) 16..50 27..30 Other", "Foo STRUCT_DEF FileId(2) 17..51 28..31 Other",
&["FileId(1) 52..55 StructLiteral", "FileId(3) 77..80 StructLiteral"], &["FileId(1) 53..56 StructLiteral", "FileId(3) 79..82 StructLiteral"],
); );
} }
@ -455,7 +455,7 @@ mod tests {
let (analysis, pos) = analysis_and_position(code); let (analysis, pos) = analysis_and_position(code);
let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); let refs = analysis.find_all_refs(pos, None).unwrap().unwrap();
check_result(refs, "foo SOURCE_FILE FileId(2) 0..35 Other", &["FileId(1) 13..16 Other"]); check_result(refs, "foo SOURCE_FILE FileId(2) 0..35 Other", &["FileId(1) 14..17 Other"]);
} }
#[test] #[test]
@ -483,7 +483,7 @@ mod tests {
check_result( check_result(
refs, refs,
"Foo STRUCT_DEF FileId(3) 0..41 18..21 Other", "Foo STRUCT_DEF FileId(3) 0..41 18..21 Other",
&["FileId(2) 20..23 Other", "FileId(2) 46..49 StructLiteral"], &["FileId(2) 20..23 Other", "FileId(2) 47..50 StructLiteral"],
); );
} }
@ -510,7 +510,7 @@ mod tests {
let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); let refs = analysis.find_all_refs(pos, None).unwrap().unwrap();
check_result( check_result(
refs, refs,
"quux FN_DEF FileId(1) 18..34 25..29 Other", "quux FN_DEF FileId(1) 19..35 26..30 Other",
&["FileId(2) 16..20 StructLiteral", "FileId(3) 16..20 StructLiteral"], &["FileId(2) 16..20 StructLiteral", "FileId(3) 16..20 StructLiteral"],
); );
@ -518,7 +518,7 @@ mod tests {
analysis.find_all_refs(pos, Some(SearchScope::single_file(bar))).unwrap().unwrap(); analysis.find_all_refs(pos, Some(SearchScope::single_file(bar))).unwrap().unwrap();
check_result( check_result(
refs, refs,
"quux FN_DEF FileId(1) 18..34 25..29 Other", "quux FN_DEF FileId(1) 19..35 26..30 Other",
&["FileId(3) 16..20 StructLiteral"], &["FileId(3) 16..20 StructLiteral"],
); );
} }
@ -637,8 +637,8 @@ mod tests {
let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); let refs = analysis.find_all_refs(pos, None).unwrap().unwrap();
check_result( check_result(
refs, refs,
"f FN_DEF FileId(1) 25..34 28..29 Other", "f FN_DEF FileId(1) 26..35 29..30 Other",
&["FileId(2) 11..12 Other", "FileId(2) 27..28 StructLiteral"], &["FileId(2) 11..12 Other", "FileId(2) 28..29 StructLiteral"],
); );
} }

View file

@ -310,11 +310,11 @@ mod tests {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 22..46, full_range: 23..47,
name: "test_foo", name: "test_foo",
kind: FN_DEF, kind: FN_DEF,
focus_range: Some( focus_range: Some(
33..41, 34..42,
), ),
container_name: None, container_name: None,
description: None, description: None,
@ -335,11 +335,11 @@ mod tests {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 47..81, full_range: 49..83,
name: "test_foo", name: "test_foo",
kind: FN_DEF, kind: FN_DEF,
focus_range: Some( focus_range: Some(
68..76, 70..78,
), ),
container_name: None, container_name: None,
description: None, description: None,
@ -360,11 +360,11 @@ mod tests {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 82..104, full_range: 85..107,
name: "bench", name: "bench",
kind: FN_DEF, kind: FN_DEF,
focus_range: Some( focus_range: Some(
94..99, 97..102,
), ),
container_name: None, container_name: None,
description: None, description: None,
@ -424,7 +424,7 @@ mod tests {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 22..64, full_range: 23..65,
name: "foo", name: "foo",
kind: FN_DEF, kind: FN_DEF,
focus_range: None, focus_range: None,
@ -489,7 +489,7 @@ mod tests {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 51..105, full_range: 52..106,
name: "foo", name: "foo",
kind: FN_DEF, kind: FN_DEF,
focus_range: None, focus_range: None,

View file

@ -178,14 +178,8 @@ fn main() {}
pub use std::collections::HashMap; pub use std::collections::HashMap;
"#, "#,
"range": { "range": {
"end": { "end": { "character": 0, "line": 6 },
"character": 0, "start": { "character": 0, "line": 0 }
"line": 7
},
"start": {
"character": 0,
"line": 0
}
} }
} }
]), ]),
@ -244,14 +238,8 @@ fn main() {}
pub use std::collections::HashMap; pub use std::collections::HashMap;
"#, "#,
"range": { "range": {
"end": { "end": { "character": 0, "line": 9 },
"character": 0, "start": { "character": 0, "line": 0 }
"line": 10
},
"start": {
"character": 0,
"line": 0
}
} }
} }
]), ]),

View file

@ -128,3 +128,85 @@ pub fn split_delim(haystack: &str, delim: char) -> Option<(&str, &str)> {
let idx = haystack.find(delim)?; let idx = haystack.find(delim)?;
Some((&haystack[..idx], &haystack[idx + delim.len_utf8()..])) Some((&haystack[..idx], &haystack[idx + delim.len_utf8()..]))
} }
pub fn trim_indent(mut text: &str) -> String {
if text.starts_with('\n') {
text = &text[1..];
}
let indent = text
.lines()
.filter(|it| !it.trim().is_empty())
.map(|it| it.len() - it.trim_start().len())
.min()
.unwrap_or(0);
lines_with_ends(text)
.map(
|line| {
if line.len() <= indent {
line.trim_start_matches(' ')
} else {
&line[indent..]
}
},
)
.collect()
}
pub fn lines_with_ends(text: &str) -> LinesWithEnds {
LinesWithEnds { text }
}
pub struct LinesWithEnds<'a> {
text: &'a str,
}
impl<'a> Iterator for LinesWithEnds<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
if self.text.is_empty() {
return None;
}
let idx = self.text.find('\n').map_or(self.text.len(), |it| it + 1);
let (res, next) = self.text.split_at(idx);
self.text = next;
Some(res)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_trim_indent() {
assert_eq!(trim_indent(""), "");
assert_eq!(
trim_indent(
"
hello
world
"
),
"hello\nworld\n"
);
assert_eq!(
trim_indent(
"
hello
world"
),
"hello\nworld"
);
assert_eq!(trim_indent(" hello\n world\n"), "hello\nworld\n");
assert_eq!(
trim_indent(
"
fn main() {
return 92;
}
"
),
"fn main() {\n return 92;\n}\n"
);
}
}

View file

@ -2,7 +2,7 @@
//! rust-analyzer database from a single string. //! rust-analyzer database from a single string.
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use stdx::split_delim; use stdx::{lines_with_ends, split_delim, trim_indent};
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub struct Fixture { pub struct Fixture {
@ -26,42 +26,30 @@ impl Fixture {
/// // - other meta /// // - other meta
/// ``` /// ```
pub fn parse(ra_fixture: &str) -> Vec<Fixture> { pub fn parse(ra_fixture: &str) -> Vec<Fixture> {
let fixture = indent_first_line(ra_fixture); let fixture = trim_indent(ra_fixture);
let margin = fixture_margin(&fixture);
let mut lines = fixture
.split('\n') // don't use `.lines` to not drop `\r\n`
.enumerate()
.filter_map(|(ix, line)| {
if line.len() >= margin {
assert!(line[..margin].trim().is_empty());
let line_content = &line[margin..];
if !line_content.starts_with("//-") {
assert!(
!line_content.contains("//-"),
r#"Metadata line {} has invalid indentation. All metadata lines need to have the same indentation.
The offending line: {:?}"#,
ix,
line
);
}
Some(line_content)
} else {
assert!(line.trim().is_empty());
None
}
});
let mut res: Vec<Fixture> = Vec::new(); let mut res: Vec<Fixture> = Vec::new();
for line in lines.by_ref() {
for (ix, line) in lines_with_ends(&fixture).enumerate() {
if line.contains("//-") {
assert!(
line.starts_with("//-"),
"Metadata line {} has invalid indentation. \
All metadata lines need to have the same indentation.\n\
The offending line: {:?}",
ix,
line
);
}
if line.starts_with("//-") { if line.starts_with("//-") {
let meta = Fixture::parse_meta_line(line); let meta = Fixture::parse_meta_line(line);
res.push(meta) res.push(meta)
} else if let Some(entry) = res.last_mut() { } else if let Some(entry) = res.last_mut() {
entry.text.push_str(line); entry.text.push_str(line);
entry.text.push('\n');
} }
} }
res res
} }
@ -118,51 +106,6 @@ The offending line: {:?}"#,
} }
} }
/// Adjusts the indentation of the first line to the minimum indentation of the rest of the lines.
/// This allows fixtures to start off in a different indentation, e.g. to align the first line with
/// the other lines visually:
/// ```
/// let fixture = "//- /lib.rs
/// mod foo;
/// //- /foo.rs
/// fn bar() {}
/// ";
/// assert_eq!(fixture_margin(fixture),
/// " //- /lib.rs
/// mod foo;
/// //- /foo.rs
/// fn bar() {}
/// ")
/// ```
fn indent_first_line(fixture: &str) -> String {
if fixture.is_empty() {
return String::new();
}
let mut lines = fixture.lines();
let first_line = lines.next().unwrap();
if first_line.contains("//-") {
let rest = lines.collect::<Vec<_>>().join("\n");
let fixed_margin = fixture_margin(&rest);
let fixed_indent = fixed_margin - indent_len(first_line);
format!("\n{}{}\n{}", " ".repeat(fixed_indent), first_line, rest)
} else {
fixture.to_owned()
}
}
fn fixture_margin(fixture: &str) -> usize {
fixture
.lines()
.filter(|it| it.trim_start().starts_with("//-"))
.map(indent_len)
.next()
.expect("empty fixture")
}
fn indent_len(s: &str) -> usize {
s.len() - s.trim_start().len()
}
#[test] #[test]
#[should_panic] #[should_panic]
fn parse_fixture_checks_further_indented_metadata() { fn parse_fixture_checks_further_indented_metadata() {
@ -178,25 +121,6 @@ fn parse_fixture_checks_further_indented_metadata() {
); );
} }
#[test]
fn parse_fixture_can_handle_dedented_first_line() {
let fixture = "//- /lib.rs
mod foo;
//- /foo.rs
struct Bar;
";
assert_eq!(
Fixture::parse(fixture),
Fixture::parse(
"//- /lib.rs
mod foo;
//- /foo.rs
struct Bar;
"
)
)
}
#[test] #[test]
fn parse_fixture_gets_full_meta() { fn parse_fixture_gets_full_meta() {
let parsed = Fixture::parse( let parsed = Fixture::parse(
@ -208,7 +132,7 @@ fn parse_fixture_gets_full_meta() {
assert_eq!(1, parsed.len()); assert_eq!(1, parsed.len());
let meta = &parsed[0]; let meta = &parsed[0];
assert_eq!("mod m;\n\n", meta.text); assert_eq!("mod m;\n", meta.text);
assert_eq!("foo", meta.crate_name.as_ref().unwrap()); assert_eq!("foo", meta.crate_name.as_ref().unwrap());
assert_eq!("/lib.rs", meta.path); assert_eq!("/lib.rs", meta.path);

View file

@ -43,7 +43,7 @@ macro_rules! assert_eq_text {
if left.trim() == right.trim() { if left.trim() == right.trim() {
eprintln!("Left:\n{:?}\n\nRight:\n{:?}\n\nWhitespace difference\n", left, right); eprintln!("Left:\n{:?}\n\nRight:\n{:?}\n\nWhitespace difference\n", left, right);
} else { } else {
let changeset = $crate::__Changeset::new(right, left, "\n"); let changeset = $crate::__Changeset::new(left, right, "\n");
eprintln!("Left:\n{}\n\nRight:\n{}\n\nDiff:\n{}\n", left, right, changeset); eprintln!("Left:\n{}\n\nRight:\n{}\n\nDiff:\n{}\n", left, right, changeset);
} }
eprintln!($($tt)*); eprintln!($($tt)*);