Fix errors in when languages have no fields
This commit is contained in:
parent
56309a1c28
commit
9f608435ee
4 changed files with 72 additions and 13 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use super::helpers::edits::{get_random_edit, perform_edit};
|
||||
use super::helpers::fixtures::{get_language, get_test_language};
|
||||
use super::helpers::random::Rand;
|
||||
use super::helpers::edits::{get_random_edit, perform_edit};
|
||||
use crate::generate::generate_parser_for_grammar;
|
||||
use tree_sitter::{Node, Parser, Point, Tree};
|
||||
|
||||
|
|
@ -321,11 +321,7 @@ fn test_node_edit() {
|
|||
let nodes_after = get_all_nodes(&tree2);
|
||||
for (i, node) in nodes_before.into_iter().enumerate() {
|
||||
assert_eq!(
|
||||
(
|
||||
node.kind(),
|
||||
node.start_byte(),
|
||||
node.start_position()
|
||||
),
|
||||
(node.kind(), node.start_byte(), node.start_position()),
|
||||
(
|
||||
nodes_after[i].kind(),
|
||||
nodes_after[i].start_byte(),
|
||||
|
|
@ -415,13 +411,18 @@ fn test_node_field_names() {
|
|||
let language = get_test_language(&parser_name, &parser_code, None);
|
||||
parser.set_language(language).unwrap();
|
||||
|
||||
let tree = parser.parse("child-0 child-1 child-2 child-3 child-4", None).unwrap();
|
||||
let tree = parser
|
||||
.parse("child-0 child-1 child-2 child-3 child-4", None)
|
||||
.unwrap();
|
||||
let root_node = tree.root_node();
|
||||
|
||||
assert_eq!(root_node.child_by_field_name("field_1"), root_node.child(0));
|
||||
assert_eq!(root_node.child_by_field_name("field_2"), root_node.child(2));
|
||||
assert_eq!(root_node.child_by_field_name("field_3"), root_node.child(4));
|
||||
assert_eq!(root_node.child(0).unwrap().child_by_field_name("field_1"), None);
|
||||
assert_eq!(
|
||||
root_node.child(0).unwrap().child_by_field_name("field_1"),
|
||||
None
|
||||
);
|
||||
assert_eq!(root_node.child_by_field_name("not_a_real_field"), None);
|
||||
|
||||
let mut cursor = root_node.walk();
|
||||
|
|
@ -443,6 +444,55 @@ fn test_node_field_names() {
|
|||
assert_eq!(cursor.field_name(), Some("field_3"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_node_field_calls_in_language_without_fields() {
|
||||
let (parser_name, parser_code) = generate_parser_for_grammar(
|
||||
r#"
|
||||
{
|
||||
"name": "test_grammar_with_no_fields",
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s+"}
|
||||
],
|
||||
"rules": {
|
||||
"a": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "b"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "c"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "d"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut parser = Parser::new();
|
||||
let language = get_test_language(&parser_name, &parser_code, None);
|
||||
parser.set_language(language).unwrap();
|
||||
|
||||
let tree = parser.parse("b c d", None).unwrap();
|
||||
|
||||
let root_node = tree.root_node();
|
||||
assert_eq!(root_node.kind(), "a");
|
||||
assert_eq!(root_node.child_by_field_name("something"), None);
|
||||
|
||||
let mut cursor = root_node.walk();
|
||||
assert_eq!(cursor.field_name(), None);
|
||||
assert_eq!(cursor.goto_first_child(), true);
|
||||
assert_eq!(cursor.field_name(), None);
|
||||
}
|
||||
|
||||
fn get_all_nodes(tree: &Tree) -> Vec<Node> {
|
||||
let mut result = Vec::new();
|
||||
let mut visited_children = false;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
#include "./error_costs.h"
|
||||
#include <string.h>
|
||||
|
||||
#define LANGUAGE_VERSION_WITH_FIELDS 10
|
||||
|
||||
void ts_language_table_entry(const TSLanguage *self, TSStateId state,
|
||||
TSSymbol symbol, TableEntry *result) {
|
||||
if (symbol == ts_builtin_sym_error || symbol == ts_builtin_sym_error_repeat) {
|
||||
|
|
@ -73,7 +71,7 @@ TSSymbolType ts_language_symbol_type(const TSLanguage *language, TSSymbol symbol
|
|||
}
|
||||
|
||||
uint32_t ts_language_field_count(const TSLanguage *self) {
|
||||
if (self->version >= LANGUAGE_VERSION_WITH_FIELDS) {
|
||||
if (self->version >= TREE_SITTER_LANGUAGE_VERSION_WITH_FIELDS) {
|
||||
return self->field_count;
|
||||
} else {
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ extern "C" {
|
|||
#include "tree_sitter/parser.h"
|
||||
|
||||
#define ts_builtin_sym_error_repeat (ts_builtin_sym_error - 1)
|
||||
#define TREE_SITTER_LANGUAGE_VERSION_WITH_FIELDS 10
|
||||
|
||||
typedef struct {
|
||||
const TSParseAction *actions;
|
||||
|
|
@ -93,6 +94,12 @@ static inline void ts_language_field_map(
|
|||
const TSFieldMapEntry **start,
|
||||
const TSFieldMapEntry **end
|
||||
) {
|
||||
if (self->version < TREE_SITTER_LANGUAGE_VERSION_WITH_FIELDS || self->field_count == 0) {
|
||||
*start = NULL;
|
||||
*end = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
TSFieldMapSlice slice = self->field_map_slices[production_id];
|
||||
*start = &self->field_map_entries[slice.index];
|
||||
*end = &self->field_map_entries[slice.index] + slice.length;
|
||||
|
|
|
|||
|
|
@ -284,6 +284,10 @@ TSFieldId ts_tree_cursor_current_field_id(const TSTreeCursor *_self) {
|
|||
|
||||
const char *ts_tree_cursor_current_field_name(const TSTreeCursor *_self) {
|
||||
TSFieldId id = ts_tree_cursor_current_field_id(_self);
|
||||
const TreeCursor *self = (const TreeCursor *)_self;
|
||||
return self->tree->language->field_names[id];
|
||||
if (id) {
|
||||
const TreeCursor *self = (const TreeCursor *)_self;
|
||||
return self->tree->language->field_names[id];
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue