Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/syntax_tree.rs')
| -rw-r--r-- | crates/ide/src/syntax_tree.rs | 338 |
1 files changed, 0 insertions, 338 deletions
diff --git a/crates/ide/src/syntax_tree.rs b/crates/ide/src/syntax_tree.rs deleted file mode 100644 index e241cb82bd..0000000000 --- a/crates/ide/src/syntax_tree.rs +++ /dev/null @@ -1,338 +0,0 @@ -use hir::Semantics; -use ide_db::{FileId, RootDatabase}; -use syntax::{ - AstNode, NodeOrToken, SourceFile, SyntaxKind::STRING, SyntaxToken, TextRange, TextSize, -}; - -// Feature: Show Syntax Tree -// -// Shows the parse tree of the current file. It exists mostly for debugging -// rust-analyzer itself. -// -// |=== -// | Editor | Action Name -// -// | VS Code | **rust-analyzer: Show Syntax Tree** -// |=== -// image::https://user-images.githubusercontent.com/48062697/113065586-068bdb80-91b1-11eb-9507-fee67f9f45a0.gif[] -pub(crate) fn syntax_tree( - db: &RootDatabase, - file_id: FileId, - text_range: Option<TextRange>, -) -> String { - let sema = Semantics::new(db); - let parse = sema.parse_guess_edition(file_id); - if let Some(text_range) = text_range { - let node = match parse.syntax().covering_element(text_range) { - NodeOrToken::Node(node) => node, - NodeOrToken::Token(token) => { - if let Some(tree) = syntax_tree_for_string(&token, text_range) { - return tree; - } - token.parent().unwrap() - } - }; - - format!("{node:#?}") - } else { - format!("{:#?}", parse.syntax()) - } -} - -/// Attempts parsing the selected contents of a string literal -/// as rust syntax and returns its syntax tree -fn syntax_tree_for_string(token: &SyntaxToken, text_range: TextRange) -> Option<String> { - // When the range is inside a string - // we'll attempt parsing it as rust syntax - // to provide the syntax tree of the contents of the string - match token.kind() { - STRING => syntax_tree_for_token(token, text_range), - _ => None, - } -} - -fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<String> { - // Range of the full node - let node_range = node.text_range(); - let text = node.text().to_owned(); - - // We start at some point inside the node - // Either we have selected the whole string - // or our selection is inside it - let start = text_range.start() - node_range.start(); - - // how many characters we have selected - let len = text_range.len(); - - let node_len = node_range.len(); - - // We want to cap our length - let len = len.min(node_len); - - // Ensure our slice is inside the actual string - let end = - if start + len < TextSize::of(&text) { start + len } else { TextSize::of(&text) - start }; - - let text = &text[TextRange::new(start, end)]; - - // Remove possible extra string quotes from the start - // and the end of the string - let text = text - .trim_start_matches('r') - .trim_start_matches('#') - .trim_start_matches('"') - .trim_end_matches('#') - .trim_end_matches('"') - .trim() - // Remove custom markers - .replace("$0", ""); - - let parsed = SourceFile::parse(&text, span::Edition::CURRENT_FIXME); - - // If the "file" parsed without errors, - // return its syntax - if parsed.errors().is_empty() { - return Some(format!("{:#?}", parsed.tree().syntax())); - } - - None -} - -#[cfg(test)] -mod tests { - use expect_test::expect; - - use crate::fixture; - - fn check(ra_fixture: &str, expect: expect_test::Expect) { - let (analysis, file_id) = fixture::file(ra_fixture); - let syn = analysis.syntax_tree(file_id, None).unwrap(); - expect.assert_eq(&syn) - } - fn check_range(ra_fixture: &str, expect: expect_test::Expect) { - let (analysis, frange) = fixture::range(ra_fixture); - let syn = analysis.syntax_tree(frange.file_id, Some(frange.range)).unwrap(); - expect.assert_eq(&syn) - } - - #[test] - fn test_syntax_tree_without_range() { - // Basic syntax - check( - r#"fn foo() {}"#, - expect![[r#" - [email protected] "fn" - [email protected] " " - [email protected] "foo" - [email protected] "(" - [email protected] ")" - [email protected] " " - [email protected] "{" - [email protected] "}" - "#]], - ); - - check( - r#" -fn test() { - assert!(" - fn foo() { - } - ", ""); -}"#, - expect![[r#" - [email protected] "fn" - [email protected] " " - [email protected] "test" - [email protected] "(" - [email protected] ")" - [email protected] " " - [email protected] "{" - [email protected] "\n " - [email protected] "assert" - [email protected] "!" - [email protected] "(" - [email protected] "\"\n fn foo() {\n ..." - [email protected] "," - [email protected] " " - [email protected] "\"\"" - [email protected] ")" - [email protected] ";" - [email protected] "\n" - [email protected] "}" - "#]], - ) - } - - #[test] - fn test_syntax_tree_with_range() { - check_range( - r#"$0fn foo() {}$0"#, - expect![[r#" - [email protected] "fn" - [email protected] " " - [email protected] "foo" - [email protected] "(" - [email protected] ")" - [email protected] " " - [email protected] "{" - [email protected] "}" - "#]], - ); - - check_range( - r#" -fn test() { - $0assert!(" - fn foo() { - } - ", "");$0 -}"#, - expect![[r#" - [email protected] "assert" - [email protected] "!" - [email protected] "(" - [email protected] "\"\n fn foo() {\n ..." - [email protected] "," - [email protected] " " - [email protected] "\"\"" - [email protected] ")" - [email protected] ";" - "#]], - ); - } - - #[test] - fn test_syntax_tree_inside_string() { - check_range( - r#"fn test() { - assert!(" -$0fn foo() { -}$0 -fn bar() { -} - ", ""); -}"#, - expect![[r#" - [email protected] "fn" - [email protected] " " - [email protected] "foo" - [email protected] "(" - [email protected] ")" - [email protected] " " - [email protected] "{" - [email protected] "\n" - [email protected] "}" - "#]], - ); - - // With a raw string - check_range( - r###"fn test() { - assert!(r#" -$0fn foo() { -}$0 -fn bar() { -} - "#, ""); -}"###, - expect![[r#" - [email protected] "fn" - [email protected] " " - [email protected] "foo" - [email protected] "(" - [email protected] ")" - [email protected] " " - [email protected] "{" - [email protected] "\n" - [email protected] "}" - "#]], - ); - - // With a raw string - check_range( - r###"fn test() { - assert!(r$0#" -fn foo() { -} -fn bar() { -}"$0#, ""); -}"###, - expect![[r#" - [email protected] "fn" - [email protected] " " - [email protected] "foo" - [email protected] "(" - [email protected] ")" - [email protected] " " - [email protected] "{" - [email protected] "\n" - [email protected] "}" - [email protected] "\n" - [email protected] "fn" - [email protected] " " - [email protected] "bar" - [email protected] "(" - [email protected] ")" - [email protected] " " - [email protected] "{" - [email protected] "\n" - [email protected] "}" - "#]], - ); - } -} |