From ea515b69679593c93b542e06ba86cab83f87ea02 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 18 Jul 2019 12:39:12 -0700 Subject: [PATCH] Fix ts_node_string behavior for anonymous leaf nodes Refs tree-sitter/py-tree-sitter#8 --- cli/src/tests/node_test.rs | 17 +++++++++++++++++ lib/src/subtree.c | 16 ++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/cli/src/tests/node_test.rs b/cli/src/tests/node_test.rs index 431267b9..4cf9fc13 100644 --- a/cli/src/tests/node_test.rs +++ b/cli/src/tests/node_test.rs @@ -419,6 +419,23 @@ fn test_node_is_extra() { assert!(comment_node.is_extra()); } +#[test] +fn test_node_sexp() { + let mut parser = Parser::new(); + parser.set_language(get_language("javascript")).unwrap(); + let tree = parser.parse("if (a) b", None).unwrap(); + let root_node = tree.root_node(); + let if_node = root_node.descendant_for_byte_range(0, 0).unwrap(); + let paren_node = root_node.descendant_for_byte_range(3, 3).unwrap(); + let identifier_node = root_node.descendant_for_byte_range(4, 4).unwrap(); + assert_eq!(if_node.kind(), "if"); + assert_eq!(if_node.to_sexp(), "(\"if\")"); + assert_eq!(paren_node.kind(), "("); + assert_eq!(paren_node.to_sexp(), "(\"(\")"); + assert_eq!(identifier_node.kind(), "identifier"); + assert_eq!(identifier_node.to_sexp(), "(identifier)"); +} + #[test] fn test_node_field_names() { let (parser_name, parser_code) = generate_parser_for_grammar( diff --git a/lib/src/subtree.c b/lib/src/subtree.c index a7521fa3..2e7d05a7 100644 --- a/lib/src/subtree.c +++ b/lib/src/subtree.c @@ -816,16 +816,16 @@ static size_t ts_subtree__write_to_string( char *cursor = string; char **writer = (limit > 0) ? &cursor : &string; - bool visible = + bool is_root = field_name == ROOT_FIELD; + bool is_visible = include_all || alias_is_named || ts_subtree_missing(self) || (ts_subtree_visible(self) && ts_subtree_named(self)); - if (visible) { - if (field_name != ROOT_FIELD) { + if (is_visible) { + if (!is_root) { cursor += snprintf(*writer, limit, " "); - if (field_name) { cursor += snprintf(*writer, limit, "%s: ", field_name); } @@ -848,6 +848,10 @@ static size_t ts_subtree__write_to_string( cursor += snprintf(*writer, limit, "(%s", symbol_name); } } + } else if (is_root) { + TSSymbol symbol = ts_subtree_symbol(self); + const char *symbol_name = ts_language_symbol_name(language, symbol); + cursor += snprintf(*writer, limit, "(\"%s\")", symbol_name); } if (ts_subtree_child_count(self)) { @@ -877,7 +881,7 @@ static size_t ts_subtree__write_to_string( ? ts_language_symbol_metadata(language, alias_symbol).named : false; - const char *child_field_name = visible ? NULL : field_name; + const char *child_field_name = is_visible ? NULL : field_name; for (const TSFieldMapEntry *i = field_map; i < field_map_end; i++) { if (!i->inherited && i->child_index == structural_child_index) { child_field_name = language->field_names[i->field_id]; @@ -895,7 +899,7 @@ static size_t ts_subtree__write_to_string( } } - if (visible) cursor += snprintf(*writer, limit, ")"); + if (is_visible) cursor += snprintf(*writer, limit, ")"); return cursor - string; }