From f48664068210b92f4884ee8e6fe8504dabcd4d9a Mon Sep 17 00:00:00 2001 From: Daiki Ihara Date: Fri, 4 Dec 2020 00:05:39 +0900 Subject: Extract tests module to file in ide_db crate --- crates/ide_db/src/helpers/insert_use/tests.rs | 620 ++++++++++++++++++++++++++ 1 file changed, 620 insertions(+) create mode 100644 crates/ide_db/src/helpers/insert_use/tests.rs (limited to 'crates/ide_db/src/helpers/insert_use/tests.rs') diff --git a/crates/ide_db/src/helpers/insert_use/tests.rs b/crates/ide_db/src/helpers/insert_use/tests.rs new file mode 100644 index 000000000..86bfa5b41 --- /dev/null +++ b/crates/ide_db/src/helpers/insert_use/tests.rs @@ -0,0 +1,620 @@ +use super::*; + +use test_utils::assert_eq_text; + +#[test] +fn insert_existing() { + check_full("std::fs", "use std::fs;", "use std::fs;") +} + +#[test] +fn insert_start() { + check_none( + "std::bar::AA", + r" +use std::bar::B; +use std::bar::D; +use std::bar::F; +use std::bar::G;", + r" +use std::bar::AA; +use std::bar::B; +use std::bar::D; +use std::bar::F; +use std::bar::G;", + ) +} + +#[test] +fn insert_start_indent() { + mark::check!(insert_use_indent_after); + check_none( + "std::bar::AA", + r" + use std::bar::B; + use std::bar::D;", + r" + use std::bar::AA; + use std::bar::B; + use std::bar::D;", + ) +} + +#[test] +fn insert_middle() { + check_none( + "std::bar::EE", + r" +use std::bar::A; +use std::bar::D; +use std::bar::F; +use std::bar::G;", + r" +use std::bar::A; +use std::bar::D; +use std::bar::EE; +use std::bar::F; +use std::bar::G;", + ) +} + +#[test] +fn insert_middle_indent() { + check_none( + "std::bar::EE", + r" + use std::bar::A; + use std::bar::D; + use std::bar::F; + use std::bar::G;", + r" + use std::bar::A; + use std::bar::D; + use std::bar::EE; + use std::bar::F; + use std::bar::G;", + ) +} + +#[test] +fn insert_end() { + check_none( + "std::bar::ZZ", + r" +use std::bar::A; +use std::bar::D; +use std::bar::F; +use std::bar::G;", + r" +use std::bar::A; +use std::bar::D; +use std::bar::F; +use std::bar::G; +use std::bar::ZZ;", + ) +} + +#[test] +fn insert_end_indent() { + mark::check!(insert_use_indent_before); + check_none( + "std::bar::ZZ", + r" + use std::bar::A; + use std::bar::D; + use std::bar::F; + use std::bar::G;", + r" + use std::bar::A; + use std::bar::D; + use std::bar::F; + use std::bar::G; + use std::bar::ZZ;", + ) +} + +#[test] +fn insert_middle_nested() { + check_none( + "std::bar::EE", + r" +use std::bar::A; +use std::bar::{D, Z}; // example of weird imports due to user +use std::bar::F; +use std::bar::G;", + r" +use std::bar::A; +use std::bar::EE; +use std::bar::{D, Z}; // example of weird imports due to user +use std::bar::F; +use std::bar::G;", + ) +} + +#[test] +fn insert_middle_groups() { + check_none( + "foo::bar::GG", + r" + use std::bar::A; + use std::bar::D; + + use foo::bar::F; + use foo::bar::H;", + r" + use std::bar::A; + use std::bar::D; + + use foo::bar::F; + use foo::bar::GG; + use foo::bar::H;", + ) +} + +#[test] +fn insert_first_matching_group() { + check_none( + "foo::bar::GG", + r" + use foo::bar::A; + use foo::bar::D; + + use std; + + use foo::bar::F; + use foo::bar::H;", + r" + use foo::bar::A; + use foo::bar::D; + use foo::bar::GG; + + use std; + + use foo::bar::F; + use foo::bar::H;", + ) +} + +#[test] +fn insert_missing_group_std() { + check_none( + "std::fmt", + r" + use foo::bar::A; + use foo::bar::D;", + r" + use std::fmt; + + use foo::bar::A; + use foo::bar::D;", + ) +} + +#[test] +fn insert_missing_group_self() { + check_none( + "self::fmt", + r" +use foo::bar::A; +use foo::bar::D;", + r" +use foo::bar::A; +use foo::bar::D; + +use self::fmt;", + ) +} + +#[test] +fn insert_no_imports() { + check_full( + "foo::bar", + "fn main() {}", + r"use foo::bar; + +fn main() {}", + ) +} + +#[test] +fn insert_empty_file() { + // empty files will get two trailing newlines + // this is due to the test case insert_no_imports above + check_full( + "foo::bar", + "", + r"use foo::bar; + +", + ) +} + +#[test] +fn insert_empty_module() { + mark::check!(insert_use_no_indent_after); + check( + "foo::bar", + "mod x {}", + r"{ + use foo::bar; +}", + None, + true, + ) +} + +#[test] +fn insert_after_inner_attr() { + check_full( + "foo::bar", + r"#![allow(unused_imports)]", + r"#![allow(unused_imports)] + +use foo::bar;", + ) +} + +#[test] +fn insert_after_inner_attr2() { + check_full( + "foo::bar", + r"#![allow(unused_imports)] + +#![no_std] +fn main() {}", + r"#![allow(unused_imports)] + +#![no_std] + +use foo::bar; +fn main() {}", + ); +} + +#[test] +fn inserts_after_single_line_inner_comments() { + check_none( + "foo::bar::Baz", + "//! Single line inner comments do not allow any code before them.", + r#"//! Single line inner comments do not allow any code before them. + +use foo::bar::Baz;"#, + ); +} + +#[test] +fn inserts_after_multiline_inner_comments() { + check_none( + "foo::bar::Baz", + r#"/*! Multiline inner comments do not allow any code before them. */ + +/*! Still an inner comment, cannot place any code before. */ +fn main() {}"#, + r#"/*! Multiline inner comments do not allow any code before them. */ + +/*! Still an inner comment, cannot place any code before. */ + +use foo::bar::Baz; +fn main() {}"#, + ) +} + +#[test] +fn inserts_after_all_inner_items() { + check_none( + "foo::bar::Baz", + r#"#![allow(unused_imports)] +/*! Multiline line comment 2 */ + + +//! Single line comment 1 +#![no_std] +//! Single line comment 2 +fn main() {}"#, + r#"#![allow(unused_imports)] +/*! Multiline line comment 2 */ + + +//! Single line comment 1 +#![no_std] +//! Single line comment 2 + +use foo::bar::Baz; +fn main() {}"#, + ) +} + +#[test] +fn merge_groups() { + check_last("std::io", r"use std::fmt;", r"use std::{fmt, io};") +} + +#[test] +fn merge_groups_last() { + check_last( + "std::io", + r"use std::fmt::{Result, Display};", + r"use std::fmt::{Result, Display}; +use std::io;", + ) +} + +#[test] +fn merge_last_into_self() { + check_last("foo::bar::baz", r"use foo::bar;", r"use foo::bar::{self, baz};"); +} + +#[test] +fn merge_groups_full() { + check_full( + "std::io", + r"use std::fmt::{Result, Display};", + r"use std::{fmt::{Result, Display}, io};", + ) +} + +#[test] +fn merge_groups_long_full() { + check_full("std::foo::bar::Baz", r"use std::foo::bar::Qux;", r"use std::foo::bar::{Baz, Qux};") +} + +#[test] +fn merge_groups_long_last() { + check_last("std::foo::bar::Baz", r"use std::foo::bar::Qux;", r"use std::foo::bar::{Baz, Qux};") +} + +#[test] +fn merge_groups_long_full_list() { + check_full( + "std::foo::bar::Baz", + r"use std::foo::bar::{Qux, Quux};", + r"use std::foo::bar::{Baz, Quux, Qux};", + ) +} + +#[test] +fn merge_groups_long_last_list() { + check_last( + "std::foo::bar::Baz", + r"use std::foo::bar::{Qux, Quux};", + r"use std::foo::bar::{Baz, Quux, Qux};", + ) +} + +#[test] +fn merge_groups_long_full_nested() { + check_full( + "std::foo::bar::Baz", + r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};", + r"use std::foo::bar::{Baz, Qux, quux::{Fez, Fizz}};", + ) +} + +#[test] +fn merge_groups_long_last_nested() { + check_last( + "std::foo::bar::Baz", + r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};", + r"use std::foo::bar::Baz; +use std::foo::bar::{Qux, quux::{Fez, Fizz}};", + ) +} + +#[test] +fn merge_groups_full_nested_deep() { + check_full( + "std::foo::bar::quux::Baz", + r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};", + r"use std::foo::bar::{Qux, quux::{Baz, Fez, Fizz}};", + ) +} + +#[test] +fn merge_groups_full_nested_long() { + check_full( + "std::foo::bar::Baz", + r"use std::{foo::bar::Qux};", + r"use std::{foo::bar::{Baz, Qux}};", + ); +} + +#[test] +fn merge_groups_last_nested_long() { + check_full( + "std::foo::bar::Baz", + r"use std::{foo::bar::Qux};", + r"use std::{foo::bar::{Baz, Qux}};", + ); +} + +#[test] +fn merge_groups_skip_pub() { + check_full( + "std::io", + r"pub use std::fmt::{Result, Display};", + r"pub use std::fmt::{Result, Display}; +use std::io;", + ) +} + +#[test] +fn merge_groups_skip_pub_crate() { + check_full( + "std::io", + r"pub(crate) use std::fmt::{Result, Display};", + r"pub(crate) use std::fmt::{Result, Display}; +use std::io;", + ) +} + +#[test] +#[ignore] // FIXME: Support this +fn split_out_merge() { + check_last( + "std::fmt::Result", + r"use std::{fmt, io};", + r"use std::fmt::{self, Result}; +use std::io;", + ) +} + +#[test] +fn merge_into_module_import() { + check_full("std::fmt::Result", r"use std::{fmt, io};", r"use std::{fmt::{self, Result}, io};") +} + +#[test] +fn merge_groups_self() { + check_full("std::fmt::Debug", r"use std::fmt;", r"use std::fmt::{self, Debug};") +} + +#[test] +fn merge_mod_into_glob() { + check_full("token::TokenKind", r"use token::TokenKind::*;", r"use token::TokenKind::{*, self};") + // FIXME: have it emit `use token::TokenKind::{self, *}`? +} + +#[test] +fn merge_self_glob() { + check_full("self", r"use self::*;", r"use self::{*, self};") + // FIXME: have it emit `use {self, *}`? +} + +#[test] +fn merge_glob_nested() { + check_full( + "foo::bar::quux::Fez", + r"use foo::bar::{Baz, quux::*};", + r"use foo::bar::{Baz, quux::{self::*, Fez}};", + ) +} + +#[test] +fn merge_nested_considers_first_segments() { + check_full( + "hir_ty::display::write_bounds_like_dyn_trait", + r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter}, method_resolution};", + r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter, write_bounds_like_dyn_trait}, method_resolution};", + ); +} + +#[test] +fn skip_merge_last_too_long() { + check_last( + "foo::bar", + r"use foo::bar::baz::Qux;", + r"use foo::bar; +use foo::bar::baz::Qux;", + ); +} + +#[test] +fn skip_merge_last_too_long2() { + check_last( + "foo::bar::baz::Qux", + r"use foo::bar;", + r"use foo::bar; +use foo::bar::baz::Qux;", + ); +} + +#[test] +fn insert_short_before_long() { + check_none( + "foo::bar", + r"use foo::bar::baz::Qux;", + r"use foo::bar; +use foo::bar::baz::Qux;", + ); +} + +#[test] +fn merge_last_fail() { + check_merge_only_fail( + r"use foo::bar::{baz::{Qux, Fez}};", + r"use foo::bar::{baaz::{Quux, Feez}};", + MergeBehaviour::Last, + ); +} + +#[test] +fn merge_last_fail1() { + check_merge_only_fail( + r"use foo::bar::{baz::{Qux, Fez}};", + r"use foo::bar::baaz::{Quux, Feez};", + MergeBehaviour::Last, + ); +} + +#[test] +fn merge_last_fail2() { + check_merge_only_fail( + r"use foo::bar::baz::{Qux, Fez};", + r"use foo::bar::{baaz::{Quux, Feez}};", + MergeBehaviour::Last, + ); +} + +#[test] +fn merge_last_fail3() { + check_merge_only_fail( + r"use foo::bar::baz::{Qux, Fez};", + r"use foo::bar::baaz::{Quux, Feez};", + MergeBehaviour::Last, + ); +} + +fn check( + path: &str, + ra_fixture_before: &str, + ra_fixture_after: &str, + mb: Option, + module: bool, +) { + let mut syntax = ast::SourceFile::parse(ra_fixture_before).tree().syntax().clone(); + if module { + syntax = syntax.descendants().find_map(ast::Module::cast).unwrap().syntax().clone(); + } + let file = super::ImportScope::from(syntax).unwrap(); + let path = ast::SourceFile::parse(&format!("use {};", path)) + .tree() + .syntax() + .descendants() + .find_map(ast::Path::cast) + .unwrap(); + + let rewriter = insert_use(&file, path, mb); + let result = rewriter.rewrite(file.as_syntax_node()).to_string(); + assert_eq_text!(&result, ra_fixture_after); +} + +fn check_full(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { + check(path, ra_fixture_before, ra_fixture_after, Some(MergeBehaviour::Full), false) +} + +fn check_last(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { + check(path, ra_fixture_before, ra_fixture_after, Some(MergeBehaviour::Last), false) +} + +fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { + check(path, ra_fixture_before, ra_fixture_after, None, false) +} + +fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehaviour) { + let use0 = ast::SourceFile::parse(ra_fixture0) + .tree() + .syntax() + .descendants() + .find_map(ast::Use::cast) + .unwrap(); + + let use1 = ast::SourceFile::parse(ra_fixture1) + .tree() + .syntax() + .descendants() + .find_map(ast::Use::cast) + .unwrap(); + + let result = try_merge_imports(&use0, &use1, mb); + assert_eq!(result.map(|u| u.to_string()), None); +} -- cgit v1.2.3