Skip to content

Commit 6d1904c

Browse files
authored
Merge pull request tree-sitter#2104 from tree-sitter/fix/ts_node_field_name_for_child
lib: fix `ts_node_field_name_for_child` implementation
2 parents a025e8e + 0261a13 commit 6d1904c

File tree

1 file changed

+47
-13
lines changed

1 file changed

+47
-13
lines changed

lib/src/node.c

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -569,24 +569,58 @@ TSNode ts_node_child_by_field_id(TSNode self, TSFieldId field_id) {
569569
return ts_node__null();
570570
}
571571

572-
const char *ts_node_field_name_for_child(TSNode self, uint32_t child_index) {
573-
const TSFieldMapEntry *field_map_start = NULL, *field_map_end = NULL;
574-
if (!ts_node_child_count(self)) {
572+
static inline const char *ts_node__field_name_from_language(TSNode self, uint32_t structural_child_index) {
573+
const TSFieldMapEntry *field_map, *field_map_end;
574+
ts_language_field_map(
575+
self.tree->language,
576+
ts_node__subtree(self).ptr->production_id,
577+
&field_map,
578+
&field_map_end
579+
);
580+
for (; field_map != field_map_end; field_map++) {
581+
if (!field_map->inherited && field_map->child_index == structural_child_index) {
582+
return self.tree->language->field_names[field_map->field_id];
583+
}
584+
}
575585
return NULL;
576-
}
586+
}
577587

578-
ts_language_field_map(
579-
self.tree->language,
580-
ts_node__subtree(self).ptr->production_id,
581-
&field_map_start,
582-
&field_map_end
583-
);
588+
const char *ts_node_field_name_for_child(TSNode self, uint32_t child_index) {
589+
TSNode result = self;
590+
bool did_descend = true;
591+
const char *inherited_field_name = NULL;
584592

585-
for (const TSFieldMapEntry *i = field_map_start; i < field_map_end; i++) {
586-
if (i->child_index == child_index) {
587-
return self.tree->language->field_names[i->field_id];
593+
while (did_descend) {
594+
did_descend = false;
595+
596+
TSNode child;
597+
uint32_t index = 0;
598+
NodeChildIterator iterator = ts_node_iterate_children(&result);
599+
while (ts_node_child_iterator_next(&iterator, &child)) {
600+
if (ts_node__is_relevant(child, true)) {
601+
if (index == child_index) {
602+
const char *field_name = ts_node__field_name_from_language(result, iterator.structural_child_index - 1);
603+
if (field_name) return field_name;
604+
return inherited_field_name;
605+
}
606+
index++;
607+
} else {
608+
uint32_t grandchild_index = child_index - index;
609+
uint32_t grandchild_count = ts_node__relevant_child_count(child, true);
610+
if (grandchild_index < grandchild_count) {
611+
const char *field_name = ts_node__field_name_from_language(result, iterator.structural_child_index - 1);
612+
if (field_name) inherited_field_name = field_name;
613+
614+
did_descend = true;
615+
result = child;
616+
child_index = grandchild_index;
617+
break;
618+
}
619+
index += grandchild_count;
620+
}
588621
}
589622
}
623+
590624
return NULL;
591625
}
592626

0 commit comments

Comments
 (0)