@@ -2030,6 +2030,57 @@ impl<I: Iterator<Item = HighlightEvent>> Iterator for Merge<I> {
2033+pub fn pretty_print_tree<W: fmt::Write>(fmt: &mut W, node: Node) -> fmt::Result {
2034+ pretty_print_tree_impl(fmt, node, true, None, 0)
2037+fn pretty_print_tree_impl<W: fmt::Write>(
2041+ field_name: Option<&str>,
2044+ fn is_visible(node: Node) -> bool {
2046+ || (node.is_named() && node.language().node_kind_is_visible(node.kind_id()))
2049+ if is_visible(node) {
2050+ let indentation_columns = depth * 2;
2051+ write!(fmt, "{:indentation_columns$}", "")?;
2053+ if let Some(field_name) = field_name {
2054+ write!(fmt, "{}: ", field_name)?;
2057+ write!(fmt, "({}", node.kind())?;
2058+ } else if is_root {
2059+ write!(fmt, "(\"{}\")", node.kind())?;
2062+ for child_idx in 0..node.child_count() {
2063+ if let Some(child) = node.child(child_idx) {
2064+ if is_visible(child) {
2065+ fmt.write_char('\n')?;
2068+ pretty_print_tree_impl(
2072+ node.field_name_for_child(child_idx as u32),
2078+ if is_visible(node) {
2033#[cfg(test)]
2084#[cfg(test)]
2034mod test {
2085mod test {
2035 use super::*;
2086 use super::*;
@@ -2201,6 +2252,63 @@ mod test {
2256+ fn assert_pretty_print(source: &str, expected: &str, start: usize, end: usize) {
2257+ let source = Rope::from_str(source);
2259+ let loader = Loader::new(Configuration { language: vec![] });
2260+ let language = get_language("Rust").unwrap();
2262+ let config = HighlightConfiguration::new(language, "", "", "").unwrap();
2263+ let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader));
2268+ .descendant_for_byte_range(start, end)
2271+ let mut output = String::new();
2272+ pretty_print_tree(&mut output, root).unwrap();
2274+ assert_eq!(expected, output);
2278+ fn test_pretty_print() {
2279+ let source = r#"/// Hello"#;
2280+ assert_pretty_print(source, "(line_comment)", 0, source.len());
2282+ // A large tree should be indented with fields:
2283+ let source = r#"fn main() {
2284+ println!("Hello, World!");
2286+ assert_pretty_print(
2289+ "(function_item\n",
2290+ " name: (identifier)\n",
2291+ " parameters: (parameters)\n",
2293+ " (expression_statement\n",
2294+ " (macro_invocation\n",
2295+ " macro: (identifier)\n",
2297+ " (string_literal))))))",
2303+ // Selecting a token should print just that token:
2304+ let source = r#"fn main() {}"#;
2305+ assert_pretty_print(source, r#"("fn")"#, 0, 1);
2307+ // Error nodes are printed as errors:
2308+ let source = r#"}{"#;
2309+ assert_pretty_print(source, "(ERROR)", 0, source.len());
2205 fn test_load_runtime_file() {
2313 fn test_load_runtime_file() {
2206 // Test to make sure we can load some data from the runtime directory.
2314 // Test to make sure we can load some data from the runtime directory.