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() ); }