mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 21:54:42 +00:00
Add optional range parameter to SyntaxTreeParams
When range is provided, instead of showing the syntax for the whole file, we'll show the syntax tree for the given range.
This commit is contained in:
parent
17aaece6b3
commit
ac52d9a1f1
4 changed files with 148 additions and 5 deletions
|
@ -38,7 +38,7 @@ mod marks;
|
|||
|
||||
use std::sync::Arc;
|
||||
|
||||
use ra_syntax::{SourceFile, TreeArc, TextRange, TextUnit, AstNode};
|
||||
use ra_syntax::{SourceFile, TreeArc, TextRange, TextUnit, AstNode, algo};
|
||||
use ra_text_edit::TextEdit;
|
||||
use ra_db::{
|
||||
SourceDatabase, CheckCanceled,
|
||||
|
@ -245,8 +245,14 @@ impl Analysis {
|
|||
|
||||
/// Returns a syntax tree represented as `String`, for debug purposes.
|
||||
// FIXME: use a better name here.
|
||||
pub fn syntax_tree(&self, file_id: FileId) -> String {
|
||||
self.db.parse(file_id).syntax().debug_dump()
|
||||
pub fn syntax_tree(&self, file_id: FileId, text_range: Option<TextRange>) -> String {
|
||||
if let Some(text_range) = text_range {
|
||||
let file = self.db.parse(file_id);
|
||||
let node = algo::find_covering_node(file.syntax(), text_range);
|
||||
node.debug_dump()
|
||||
} else {
|
||||
self.db.parse(file_id).syntax().debug_dump()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an edit to remove all newlines in the range, cleaning up minor
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use insta::assert_debug_snapshot_matches;
|
||||
use ra_ide_api::{
|
||||
mock_analysis::{single_file, single_file_with_position, MockAnalysis},
|
||||
mock_analysis::{single_file, single_file_with_position, single_file_with_range, MockAnalysis},
|
||||
AnalysisChange, CrateGraph, Edition::Edition2018, Query, NavigationTarget,
|
||||
ReferenceSearchResult,
|
||||
};
|
||||
|
@ -138,3 +138,137 @@ mod foo {
|
|||
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()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,9 @@ pub fn handle_analyzer_status(world: ServerWorld, _: ()) -> Result<String> {
|
|||
|
||||
pub fn handle_syntax_tree(world: ServerWorld, params: req::SyntaxTreeParams) -> Result<String> {
|
||||
let id = params.text_document.try_conv_with(&world)?;
|
||||
let res = world.analysis().syntax_tree(id);
|
||||
let line_index = world.analysis().file_line_index(id);
|
||||
let text_range = params.range.map(|p| p.conv_with(&line_index));
|
||||
let res = world.analysis().syntax_tree(id, text_range);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ impl Request for SyntaxTree {
|
|||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SyntaxTreeParams {
|
||||
pub text_document: TextDocumentIdentifier,
|
||||
pub range: Option<Range>,
|
||||
}
|
||||
|
||||
pub enum ExtendSelection {}
|
||||
|
|
Loading…
Reference in a new issue