diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide_api/src/parent_module.rs index 603c3db6ae..27788c9846 100644 --- a/crates/ra_ide_api/src/parent_module.rs +++ b/crates/ra_ide_api/src/parent_module.rs @@ -28,7 +28,11 @@ pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec { #[cfg(test)] mod tests { - use crate::mock_analysis::analysis_and_position; + use crate::{ + AnalysisChange, CrateGraph, + mock_analysis::{analysis_and_position, MockAnalysis}, + Edition::Edition2018, +}; #[test] fn test_resolve_parent_module() { @@ -59,4 +63,28 @@ mod tests { let nav = analysis.parent_module(pos).unwrap().pop().unwrap(); nav.assert_match("baz MODULE FileId(1) [32; 44)"); } + + #[test] + fn test_resolve_crate_root() { + let mock = MockAnalysis::with_files( + " + //- /bar.rs + mod foo; + //- /foo.rs + // empty <|> + ", + ); + let root_file = mock.id_of("/bar.rs"); + let mod_file = mock.id_of("/foo.rs"); + let mut host = mock.analysis_host(); + assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); + + let mut crate_graph = CrateGraph::default(); + let crate_id = crate_graph.add_crate_root(root_file, Edition2018); + let mut change = AnalysisChange::new(); + change.set_crate_graph(crate_graph); + host.apply_change(change); + + assert_eq!(host.analysis().crate_for(mod_file).unwrap(), vec![crate_id]); + } } diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index 22741445ad..20bbf11a38 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs @@ -216,9 +216,55 @@ mod tests { use crate::{ mock_analysis::single_file_with_position, mock_analysis::analysis_and_position, - FileId + FileId, ReferenceSearchResult }; + #[test] + fn test_find_all_refs_for_local() { + let code = r#" + fn main() { + let mut i = 1; + let j = 1; + i = i<|> + j; + + { + i = 0; + } + + i = 5; + }"#; + + let refs = get_all_refs(code); + assert_eq!(refs.len(), 5); + } + + #[test] + fn test_find_all_refs_for_param_inside() { + let code = r#" + fn foo(i : u32) -> u32 { + i<|> + }"#; + + let refs = get_all_refs(code); + assert_eq!(refs.len(), 2); + } + + #[test] + fn test_find_all_refs_for_fn_param() { + let code = r#" + fn foo(i<|> : u32) -> u32 { + i + }"#; + + let refs = get_all_refs(code); + assert_eq!(refs.len(), 2); + } + + fn get_all_refs(text: &str) -> ReferenceSearchResult { + let (analysis, position) = single_file_with_position(text); + analysis.find_all_refs(position).unwrap().unwrap() + } + #[test] fn test_rename_for_local() { test_rename( diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs index 0978d164a4..0eadc4e719 100644 --- a/crates/ra_ide_api/src/symbol_index.rs +++ b/crates/ra_ide_api/src/symbol_index.rs @@ -270,3 +270,61 @@ fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option { container_name: None, }) } + +#[cfg(test)] +mod tests { + use ra_syntax::SmolStr; + use crate::{ + navigation_target::NavigationTarget, + mock_analysis::single_file, + Query, +}; + + #[test] + fn test_world_symbols_with_no_container() { + let code = r#" + enum FooInner { } + "#; + + let mut symbols = get_symbols_matching(code, "FooInner"); + + let s = symbols.pop().unwrap(); + + assert_eq!(s.name(), "FooInner"); + assert!(s.container_name().is_none()); + } + + #[test] + fn test_world_symbols_include_container_name() { + let code = r#" +fn foo() { + enum FooInner { } +} + "#; + + let mut symbols = get_symbols_matching(code, "FooInner"); + + let s = symbols.pop().unwrap(); + + assert_eq!(s.name(), "FooInner"); + assert_eq!(s.container_name(), Some(&SmolStr::new("foo"))); + + let code = r#" +mod foo { + struct FooInner; +} + "#; + + let mut symbols = get_symbols_matching(code, "FooInner"); + + let s = symbols.pop().unwrap(); + + assert_eq!(s.name(), "FooInner"); + assert_eq!(s.container_name(), Some(&SmolStr::new("foo"))); + } + + fn get_symbols_matching(text: &str, query: &str) -> Vec { + let (analysis, _) = single_file(text); + analysis.symbol_search(Query::new(query.into())).unwrap() + } +} diff --git a/crates/ra_ide_api/src/syntax_tree.rs b/crates/ra_ide_api/src/syntax_tree.rs index bbe9222b42..276f8a8c8a 100644 --- a/crates/ra_ide_api/src/syntax_tree.rs +++ b/crates/ra_ide_api/src/syntax_tree.rs @@ -85,3 +85,260 @@ fn syntax_tree_for_token(node: &T, text_range: TextRange) -> Option None } + +#[cfg(test)] +mod tests { + use crate::mock_analysis::{single_file, single_file_with_range}; + + #[test] + fn test_syntax_tree_without_range() { + // Basic syntax + let (analysis, file_id) = single_file(r#"fn foo() {}"#); + let syn = analysis.syntax_tree(file_id, None); + + assert_eq!( + syn.trim(), + r#" +SOURCE_FILE@[0; 11) + FN_DEF@[0; 11) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK@[9; 11) + L_CURLY@[9; 10) + R_CURLY@[10; 11) + "# + .trim() + ); + + let (analysis, file_id) = single_file( + r#" +fn test() { + assert!(" + fn foo() { + } + ", ""); +}"# + .trim(), + ); + let syn = analysis.syntax_tree(file_id, None); + + assert_eq!( + syn.trim(), + r#" +SOURCE_FILE@[0; 60) + FN_DEF@[0; 60) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 7) + IDENT@[3; 7) "test" + PARAM_LIST@[7; 9) + L_PAREN@[7; 8) + R_PAREN@[8; 9) + WHITESPACE@[9; 10) + BLOCK@[10; 60) + L_CURLY@[10; 11) + WHITESPACE@[11; 16) + EXPR_STMT@[16; 58) + MACRO_CALL@[16; 57) + PATH@[16; 22) + PATH_SEGMENT@[16; 22) + NAME_REF@[16; 22) + IDENT@[16; 22) "assert" + EXCL@[22; 23) + TOKEN_TREE@[23; 57) + L_PAREN@[23; 24) + STRING@[24; 52) + COMMA@[52; 53) + WHITESPACE@[53; 54) + STRING@[54; 56) + R_PAREN@[56; 57) + SEMI@[57; 58) + WHITESPACE@[58; 59) + R_CURLY@[59; 60) + "# + .trim() + ); + } + + #[test] + fn test_syntax_tree_with_range() { + let (analysis, range) = single_file_with_range(r#"<|>fn foo() {}<|>"#.trim()); + let syn = analysis.syntax_tree(range.file_id, Some(range.range)); + + assert_eq!( + syn.trim(), + r#" +FN_DEF@[0; 11) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK@[9; 11) + L_CURLY@[9; 10) + R_CURLY@[10; 11) + "# + .trim() + ); + + let (analysis, range) = single_file_with_range( + r#"fn test() { + <|>assert!(" + fn foo() { + } + ", "");<|> +}"# + .trim(), + ); + let syn = analysis.syntax_tree(range.file_id, Some(range.range)); + + assert_eq!( + syn.trim(), + r#" +EXPR_STMT@[16; 58) + MACRO_CALL@[16; 57) + PATH@[16; 22) + PATH_SEGMENT@[16; 22) + NAME_REF@[16; 22) + IDENT@[16; 22) "assert" + EXCL@[22; 23) + TOKEN_TREE@[23; 57) + L_PAREN@[23; 24) + STRING@[24; 52) + COMMA@[52; 53) + WHITESPACE@[53; 54) + STRING@[54; 56) + R_PAREN@[56; 57) + SEMI@[57; 58) + "# + .trim() + ); + } + + #[test] + fn test_syntax_tree_inside_string() { + let (analysis, range) = single_file_with_range( + r#"fn test() { + assert!(" +<|>fn foo() { +}<|> +fn bar() { +} + ", ""); +}"# + .trim(), + ); + let syn = analysis.syntax_tree(range.file_id, Some(range.range)); + assert_eq!( + syn.trim(), + r#" +SOURCE_FILE@[0; 12) + FN_DEF@[0; 12) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK@[9; 12) + L_CURLY@[9; 10) + WHITESPACE@[10; 11) + R_CURLY@[11; 12) +"# + .trim() + ); + + // With a raw string + let (analysis, range) = single_file_with_range( + r###"fn test() { + assert!(r#" +<|>fn foo() { +}<|> +fn bar() { +} + "#, ""); +}"### + .trim(), + ); + let syn = analysis.syntax_tree(range.file_id, Some(range.range)); + assert_eq!( + syn.trim(), + r#" +SOURCE_FILE@[0; 12) + FN_DEF@[0; 12) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK@[9; 12) + L_CURLY@[9; 10) + WHITESPACE@[10; 11) + R_CURLY@[11; 12) +"# + .trim() + ); + + // With a raw string + let (analysis, range) = single_file_with_range( + r###"fn test() { + assert!(r<|>#" +fn foo() { +} +fn bar() { +}"<|>#, ""); +}"### + .trim(), + ); + let syn = analysis.syntax_tree(range.file_id, Some(range.range)); + assert_eq!( + syn.trim(), + r#" +SOURCE_FILE@[0; 25) + FN_DEF@[0; 12) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK@[9; 12) + L_CURLY@[9; 10) + WHITESPACE@[10; 11) + R_CURLY@[11; 12) + WHITESPACE@[12; 13) + FN_DEF@[13; 25) + FN_KW@[13; 15) + WHITESPACE@[15; 16) + NAME@[16; 19) + IDENT@[16; 19) "bar" + PARAM_LIST@[19; 21) + L_PAREN@[19; 20) + R_PAREN@[20; 21) + WHITESPACE@[21; 22) + BLOCK@[22; 25) + L_CURLY@[22; 23) + WHITESPACE@[23; 24) + R_CURLY@[24; 25) + +"# + .trim() + ); + } +} diff --git a/crates/ra_ide_api/tests/test/main.rs b/crates/ra_ide_api/tests/test/main.rs deleted file mode 100644 index d4ff21c09c..0000000000 --- a/crates/ra_ide_api/tests/test/main.rs +++ /dev/null @@ -1,376 +0,0 @@ -use ra_ide_api::{ - mock_analysis::{single_file, single_file_with_position, single_file_with_range, MockAnalysis}, - AnalysisChange, CrateGraph, Edition::Edition2018, Query, NavigationTarget, - ReferenceSearchResult, -}; -use ra_syntax::SmolStr; - -#[test] -fn test_resolve_crate_root() { - let mock = MockAnalysis::with_files( - " - //- /bar.rs - mod foo; - //- /foo.rs - // empty <|> - ", - ); - let root_file = mock.id_of("/bar.rs"); - let mod_file = mock.id_of("/foo.rs"); - let mut host = mock.analysis_host(); - assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); - - let mut crate_graph = CrateGraph::default(); - let crate_id = crate_graph.add_crate_root(root_file, Edition2018); - let mut change = AnalysisChange::new(); - change.set_crate_graph(crate_graph); - host.apply_change(change); - - assert_eq!(host.analysis().crate_for(mod_file).unwrap(), vec![crate_id]); -} - -fn get_all_refs(text: &str) -> ReferenceSearchResult { - let (analysis, position) = single_file_with_position(text); - analysis.find_all_refs(position).unwrap().unwrap() -} - -fn get_symbols_matching(text: &str, query: &str) -> Vec { - let (analysis, _) = single_file(text); - analysis.symbol_search(Query::new(query.into())).unwrap() -} - -#[test] -fn test_find_all_refs_for_local() { - let code = r#" - fn main() { - let mut i = 1; - let j = 1; - i = i<|> + j; - - { - i = 0; - } - - i = 5; - }"#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 5); -} - -#[test] -fn test_find_all_refs_for_param_inside() { - let code = r#" - fn foo(i : u32) -> u32 { - i<|> - }"#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 2); -} - -#[test] -fn test_find_all_refs_for_fn_param() { - let code = r#" - fn foo(i<|> : u32) -> u32 { - i - }"#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 2); -} - -#[test] -fn test_world_symbols_with_no_container() { - let code = r#" - enum FooInner { } - "#; - - let mut symbols = get_symbols_matching(code, "FooInner"); - - let s = symbols.pop().unwrap(); - - assert_eq!(s.name(), "FooInner"); - assert!(s.container_name().is_none()); -} - -#[test] -fn test_world_symbols_include_container_name() { - let code = r#" -fn foo() { - enum FooInner { } -} - "#; - - let mut symbols = get_symbols_matching(code, "FooInner"); - - let s = symbols.pop().unwrap(); - - assert_eq!(s.name(), "FooInner"); - assert_eq!(s.container_name(), Some(&SmolStr::new("foo"))); - - let code = r#" -mod foo { - struct FooInner; -} - "#; - - let mut symbols = get_symbols_matching(code, "FooInner"); - - let s = symbols.pop().unwrap(); - - assert_eq!(s.name(), "FooInner"); - assert_eq!(s.container_name(), Some(&SmolStr::new("foo"))); -} - -#[test] -fn test_syntax_tree_without_range() { - // Basic syntax - let (analysis, file_id) = single_file(r#"fn foo() {}"#); - let syn = analysis.syntax_tree(file_id, None); - - assert_eq!( - syn.trim(), - r#" -SOURCE_FILE@[0; 11) - FN_DEF@[0; 11) - FN_KW@[0; 2) - WHITESPACE@[2; 3) - NAME@[3; 6) - IDENT@[3; 6) "foo" - PARAM_LIST@[6; 8) - L_PAREN@[6; 7) - R_PAREN@[7; 8) - WHITESPACE@[8; 9) - BLOCK@[9; 11) - L_CURLY@[9; 10) - R_CURLY@[10; 11) - "# - .trim() - ); - - let (analysis, file_id) = single_file( - r#" -fn test() { - assert!(" - fn foo() { - } - ", ""); -}"# - .trim(), - ); - let syn = analysis.syntax_tree(file_id, None); - - assert_eq!( - syn.trim(), - r#" -SOURCE_FILE@[0; 60) - FN_DEF@[0; 60) - FN_KW@[0; 2) - WHITESPACE@[2; 3) - NAME@[3; 7) - IDENT@[3; 7) "test" - PARAM_LIST@[7; 9) - L_PAREN@[7; 8) - R_PAREN@[8; 9) - WHITESPACE@[9; 10) - BLOCK@[10; 60) - L_CURLY@[10; 11) - WHITESPACE@[11; 16) - EXPR_STMT@[16; 58) - MACRO_CALL@[16; 57) - PATH@[16; 22) - PATH_SEGMENT@[16; 22) - NAME_REF@[16; 22) - IDENT@[16; 22) "assert" - EXCL@[22; 23) - TOKEN_TREE@[23; 57) - L_PAREN@[23; 24) - STRING@[24; 52) - COMMA@[52; 53) - WHITESPACE@[53; 54) - STRING@[54; 56) - R_PAREN@[56; 57) - SEMI@[57; 58) - WHITESPACE@[58; 59) - R_CURLY@[59; 60) - "# - .trim() - ); -} - -#[test] -fn test_syntax_tree_with_range() { - let (analysis, range) = single_file_with_range(r#"<|>fn foo() {}<|>"#.trim()); - let syn = analysis.syntax_tree(range.file_id, Some(range.range)); - - assert_eq!( - syn.trim(), - r#" -FN_DEF@[0; 11) - FN_KW@[0; 2) - WHITESPACE@[2; 3) - NAME@[3; 6) - IDENT@[3; 6) "foo" - PARAM_LIST@[6; 8) - L_PAREN@[6; 7) - R_PAREN@[7; 8) - WHITESPACE@[8; 9) - BLOCK@[9; 11) - L_CURLY@[9; 10) - R_CURLY@[10; 11) - "# - .trim() - ); - - let (analysis, range) = single_file_with_range( - r#"fn test() { - <|>assert!(" - fn foo() { - } - ", "");<|> -}"# - .trim(), - ); - let syn = analysis.syntax_tree(range.file_id, Some(range.range)); - - assert_eq!( - syn.trim(), - r#" -EXPR_STMT@[16; 58) - MACRO_CALL@[16; 57) - PATH@[16; 22) - PATH_SEGMENT@[16; 22) - NAME_REF@[16; 22) - IDENT@[16; 22) "assert" - EXCL@[22; 23) - TOKEN_TREE@[23; 57) - L_PAREN@[23; 24) - STRING@[24; 52) - COMMA@[52; 53) - WHITESPACE@[53; 54) - STRING@[54; 56) - R_PAREN@[56; 57) - SEMI@[57; 58) - "# - .trim() - ); -} - -#[test] -fn test_syntax_tree_inside_string() { - let (analysis, range) = single_file_with_range( - r#"fn test() { - assert!(" -<|>fn foo() { -}<|> -fn bar() { -} - ", ""); -}"# - .trim(), - ); - let syn = analysis.syntax_tree(range.file_id, Some(range.range)); - assert_eq!( - syn.trim(), - r#" -SOURCE_FILE@[0; 12) - FN_DEF@[0; 12) - FN_KW@[0; 2) - WHITESPACE@[2; 3) - NAME@[3; 6) - IDENT@[3; 6) "foo" - PARAM_LIST@[6; 8) - L_PAREN@[6; 7) - R_PAREN@[7; 8) - WHITESPACE@[8; 9) - BLOCK@[9; 12) - L_CURLY@[9; 10) - WHITESPACE@[10; 11) - R_CURLY@[11; 12) -"# - .trim() - ); - - // With a raw string - let (analysis, range) = single_file_with_range( - r###"fn test() { - assert!(r#" -<|>fn foo() { -}<|> -fn bar() { -} - "#, ""); -}"### - .trim(), - ); - let syn = analysis.syntax_tree(range.file_id, Some(range.range)); - assert_eq!( - syn.trim(), - r#" -SOURCE_FILE@[0; 12) - FN_DEF@[0; 12) - FN_KW@[0; 2) - WHITESPACE@[2; 3) - NAME@[3; 6) - IDENT@[3; 6) "foo" - PARAM_LIST@[6; 8) - L_PAREN@[6; 7) - R_PAREN@[7; 8) - WHITESPACE@[8; 9) - BLOCK@[9; 12) - L_CURLY@[9; 10) - WHITESPACE@[10; 11) - R_CURLY@[11; 12) -"# - .trim() - ); - - // With a raw string - let (analysis, range) = single_file_with_range( - r###"fn test() { - assert!(r<|>#" -fn foo() { -} -fn bar() { -}"<|>#, ""); -}"### - .trim(), - ); - let syn = analysis.syntax_tree(range.file_id, Some(range.range)); - assert_eq!( - syn.trim(), - r#" -SOURCE_FILE@[0; 25) - FN_DEF@[0; 12) - FN_KW@[0; 2) - WHITESPACE@[2; 3) - NAME@[3; 6) - IDENT@[3; 6) "foo" - PARAM_LIST@[6; 8) - L_PAREN@[6; 7) - R_PAREN@[7; 8) - WHITESPACE@[8; 9) - BLOCK@[9; 12) - L_CURLY@[9; 10) - WHITESPACE@[10; 11) - R_CURLY@[11; 12) - WHITESPACE@[12; 13) - FN_DEF@[13; 25) - FN_KW@[13; 15) - WHITESPACE@[15; 16) - NAME@[16; 19) - IDENT@[16; 19) "bar" - PARAM_LIST@[19; 21) - L_PAREN@[19; 20) - R_PAREN@[20; 21) - WHITESPACE@[21; 22) - BLOCK@[22; 25) - L_CURLY@[22; 23) - WHITESPACE@[23; 24) - R_CURLY@[24; 25) - -"# - .trim() - ); -}