From 28011b1e60b687dee30b55da4088cf6893aa0c21 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 19 Jun 2019 15:58:29 -0700 Subject: [PATCH] Add ts_node_is_extra API --- cli/src/tests/node_test.rs | 15 ++ lib/binding_rust/bindings.rs | 382 +++++++++++++++++++++++++++------- lib/binding_rust/lib.rs | 4 + lib/include/tree_sitter/api.h | 8 +- lib/src/node.c | 4 + 5 files changed, 339 insertions(+), 74 deletions(-) diff --git a/cli/src/tests/node_test.rs b/cli/src/tests/node_test.rs index 879f3f81..431267b9 100644 --- a/cli/src/tests/node_test.rs +++ b/cli/src/tests/node_test.rs @@ -404,6 +404,21 @@ fn test_node_edit() { } } +#[test] +fn test_node_is_extra() { + let mut parser = Parser::new(); + parser.set_language(get_language("javascript")).unwrap(); + let tree = parser.parse("foo(/* hi */);", None).unwrap(); + + let root_node = tree.root_node(); + let comment_node = root_node.descendant_for_byte_range(7, 7).unwrap(); + + assert_eq!(root_node.kind(), "program"); + assert_eq!(comment_node.kind(), "comment"); + assert!(!root_node.is_extra()); + assert!(comment_node.is_extra()); +} + #[test] fn test_node_field_names() { let (parser_name, parser_code) = generate_parser_for_grammar( diff --git a/lib/binding_rust/bindings.rs b/lib/binding_rust/bindings.rs index 68b167a0..c205aeb4 100644 --- a/lib/binding_rust/bindings.rs +++ b/lib/binding_rust/bindings.rs @@ -94,187 +94,361 @@ pub struct TSTreeCursor { pub context: [u32; 2usize], } extern "C" { + #[doc = " Create a new parser."] pub fn ts_parser_new() -> *mut TSParser; } extern "C" { - pub fn ts_parser_delete(arg1: *mut TSParser); + #[doc = " Delete the parser, freeing all of the memory that it used."] + pub fn ts_parser_delete(parser: *mut TSParser); } extern "C" { - pub fn ts_parser_language(arg1: *const TSParser) -> *const TSLanguage; + #[doc = " Set the language that the parser should use for parsing."] + #[doc = ""] + #[doc = " Returns a boolean indicating whether or not the language was successfully"] + #[doc = " assigned. True means assignment succeeded. False means there was a version"] + #[doc = " mismatch: the language was generated with an incompatible version of the"] + #[doc = " Tree-sitter CLI. Check the language\'s version using `ts_language_version`"] + #[doc = " and compare it to this library\'s `TREE_SITTER_LANGUAGE_VERSION` and"] + #[doc = " `TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION` constants."] + pub fn ts_parser_set_language(self_: *mut TSParser, language: *const TSLanguage) -> bool; } extern "C" { - pub fn ts_parser_set_language(arg1: *mut TSParser, arg2: *const TSLanguage) -> bool; + #[doc = " Get the parser\'s current language."] + pub fn ts_parser_language(self_: *const TSParser) -> *const TSLanguage; } extern "C" { - pub fn ts_parser_logger(arg1: *const TSParser) -> TSLogger; + #[doc = " Set the spans of text that the parser should include when parsing."] + #[doc = ""] + #[doc = " By default, the parser will always include entire documents. This function"] + #[doc = " allows you to parse only a *portion* of a document but still return a syntax"] + #[doc = " tree whose ranges match up with the document as a whole. You can also pass"] + #[doc = " multiple disjoint ranges."] + #[doc = ""] + #[doc = " The second and third parameters specify the location and length of an array"] + #[doc = " of ranges. The parser does *not* take ownership of these ranges; it copies"] + #[doc = " the data, so it doesn\'t matter how these ranges are allocated."] + pub fn ts_parser_set_included_ranges(self_: *mut TSParser, ranges: *const TSRange, length: u32); } extern "C" { - pub fn ts_parser_set_logger(arg1: *mut TSParser, arg2: TSLogger); + #[doc = " Get the ranges of text that the parser will include when parsing."] + #[doc = ""] + #[doc = " The returned pointer is owned by the parser. The caller should not free it"] + #[doc = " or write to it. The length of the array will be written to the given"] + #[doc = " `length` pointer."] + pub fn ts_parser_included_ranges(self_: *const TSParser, length: *mut u32) -> *const TSRange; } extern "C" { - pub fn ts_parser_print_dot_graphs(arg1: *mut TSParser, arg2: ::std::os::raw::c_int); -} -extern "C" { - pub fn ts_parser_halt_on_error(arg1: *mut TSParser, arg2: bool); -} -extern "C" { - pub fn ts_parser_parse(arg1: *mut TSParser, arg2: *const TSTree, arg3: TSInput) -> *mut TSTree; + #[doc = " Use the parser to parse some source code and create a syntax tree."] + #[doc = ""] + #[doc = " If you are parsing this document for the first time, pass `NULL` for the"] + #[doc = " `old_tree` parameter. Otherwise, if you have already parsed an earlier"] + #[doc = " version of this document and the document has since been edited, pass the"] + #[doc = " previous syntax tree so that the unchanged parts of it can be reused."] + #[doc = " This will save time and memory. For this to work correctly, you must have"] + #[doc = " already edited the old syntax tree using the `ts_tree_edit` function in a"] + #[doc = " way that exactly matches the source code changes."] + #[doc = ""] + #[doc = " The `TSInput` parameter lets you specify how to read the text. It has the"] + #[doc = " following three fields:"] + #[doc = " 1. `read`: A function to retrieve a chunk of text at a given byte offset"] + #[doc = " and (row, column) position. The function should return a pointer to the"] + #[doc = " text and write its length to the the `bytes_read` pointer. The parser"] + #[doc = " does not take ownership of this buffer; it just borrows it until it has"] + #[doc = " finished reading it. The function should write a zero value to the"] + #[doc = " `bytes_read` pointer to indicate the end of the document."] + #[doc = " 2. `payload`: An arbitrary pointer that will be passed to each invocation"] + #[doc = " of the `read` function."] + #[doc = " 3. `encoding`: An indication of how the text is encoded. Either"] + #[doc = " `TSInputEncodingUTF8` or `TSInputEncodingUTF16`."] + #[doc = ""] + #[doc = " This function returns a syntax tree on success, and `NULL` on failure. There"] + #[doc = " are three possible reasons for failure:"] + #[doc = " 1. The parser does not have a language assigned. Check for this using the"] + #[doc = "`ts_parser_language` function."] + #[doc = " 2. Parsing was cancelled due to a timeout that was set by an earlier call to"] + #[doc = " the `ts_parser_set_timeout_micros` function. You can resume parsing from"] + #[doc = " where the parser left out by calling `ts_parser_parse` again with the"] + #[doc = " same arguments. Or you can start parsing from scratch by first calling"] + #[doc = " `ts_parser_reset`."] + #[doc = " 3. Parsing was cancelled using a cancellation flag that was set by an"] + #[doc = " earlier call to `ts_parser_set_cancellation_flag`. You can resume parsing"] + #[doc = " from where the parser left out by calling `ts_parser_parse` again with"] + #[doc = " the same arguments."] + pub fn ts_parser_parse( + self_: *mut TSParser, + old_tree: *const TSTree, + input: TSInput, + ) -> *mut TSTree; } extern "C" { + #[doc = " Use the parser to parse some source code stored in one contiguous buffer."] + #[doc = " The first two parameters are the same as in the `ts_parser_parse` function"] + #[doc = " above. The second two parameters indicate the location of the buffer and its"] + #[doc = " length in bytes."] pub fn ts_parser_parse_string( - arg1: *mut TSParser, - arg2: *const TSTree, - arg3: *const ::std::os::raw::c_char, - arg4: u32, + self_: *mut TSParser, + old_tree: *const TSTree, + string: *const ::std::os::raw::c_char, + length: u32, ) -> *mut TSTree; } extern "C" { + #[doc = " Use the parser to parse some source code stored in one contiguous buffer with"] + #[doc = " a given encoding. The first four parameters work the same as in the"] + #[doc = " `ts_parser_parse_string` method above. The final parameter indicates whether"] + #[doc = " the text is encoded as UTF8 or UTF16."] pub fn ts_parser_parse_string_encoding( - arg1: *mut TSParser, - arg2: *const TSTree, - arg3: *const ::std::os::raw::c_char, - arg4: u32, - arg5: TSInputEncoding, + self_: *mut TSParser, + old_tree: *const TSTree, + string: *const ::std::os::raw::c_char, + length: u32, + encoding: TSInputEncoding, ) -> *mut TSTree; } extern "C" { - pub fn ts_parser_cancellation_flag(arg1: *const TSParser) -> *const usize; + #[doc = " Instruct the parser to start the next parse from the beginning."] + #[doc = ""] + #[doc = " If the parser previously failed because of a timeout or a cancellation, then"] + #[doc = " by default, it will resume where it left off on the next call to"] + #[doc = " `ts_parser_parse` or other parsing functions. If you don\'t want to resume,"] + #[doc = " and instead intend to use this parser to parse some other document, you must"] + #[doc = " call this `ts_parser_reset` first."] + pub fn ts_parser_reset(self_: *mut TSParser); } extern "C" { - pub fn ts_parser_set_cancellation_flag(arg1: *mut TSParser, arg2: *const usize); + #[doc = " Set the maximum duration in microseconds that parsing should be allowed to"] + #[doc = " take before halting. If parsing takes longer than this, it will halt early,"] + #[doc = " returning NULL. See `ts_parser_parse` for more information."] + pub fn ts_parser_set_timeout_micros(self_: *mut TSParser, timeout: u64); } extern "C" { - pub fn ts_parser_timeout_micros(arg1: *const TSParser) -> u64; + #[doc = " Get the duration in microseconds that parsing is allowed to take."] + pub fn ts_parser_timeout_micros(self_: *const TSParser) -> u64; } extern "C" { - pub fn ts_parser_set_timeout_micros(arg1: *mut TSParser, arg2: u64); + #[doc = " Set the parser\'s current cancellation flag pointer. If a non-null pointer is"] + #[doc = " assigned, then the parser will periodically read from this pointer during"] + #[doc = " parsing. If it reads a non-zero value, it will halt early, returning NULL."] + #[doc = " See `ts_parser_parse` for more information."] + pub fn ts_parser_set_cancellation_flag(self_: *mut TSParser, flag: *const usize); } extern "C" { - pub fn ts_parser_reset(arg1: *mut TSParser); + #[doc = " Get the parser\'s current cancellation flag pointer."] + pub fn ts_parser_cancellation_flag(self_: *const TSParser) -> *const usize; } extern "C" { - pub fn ts_parser_set_included_ranges(arg1: *mut TSParser, arg2: *const TSRange, arg3: u32); + #[doc = " Set the logger that a parser should use during parsing."] + #[doc = ""] + #[doc = " The parser does not take ownership over the logger payload. If a logger was"] + #[doc = " previously assigned, the caller is responsible for releasing any memory"] + #[doc = " owned by the previous logger."] + pub fn ts_parser_set_logger(self_: *mut TSParser, logger: TSLogger); } extern "C" { - pub fn ts_parser_included_ranges(arg1: *const TSParser, arg2: *mut u32) -> *const TSRange; + #[doc = " Get the parser\'s current logger."] + pub fn ts_parser_logger(self_: *const TSParser) -> TSLogger; } extern "C" { - pub fn ts_tree_copy(arg1: *const TSTree) -> *mut TSTree; + #[doc = " Set the file descriptor to which the parser should write debugging graphs"] + #[doc = " during parsing. The graphs are formatted in the DOT language. You may want"] + #[doc = " to pipe these graphs directly to a `dot(1)` process in order to generate"] + #[doc = " SVG output. You can turn off this logging by passing a negative number."] + pub fn ts_parser_print_dot_graphs(self_: *mut TSParser, file: ::std::os::raw::c_int); } extern "C" { - pub fn ts_tree_delete(arg1: *mut TSTree); + #[doc = " Set whether or not the parser should halt immediately upon detecting an"] + #[doc = " error. This will generally result in a syntax tree with an error at the"] + #[doc = " root, and one or more partial syntax trees within the error. This behavior"] + #[doc = " may not be supported long-term."] + pub fn ts_parser_halt_on_error(self_: *mut TSParser, halt: bool); } extern "C" { - pub fn ts_tree_root_node(arg1: *const TSTree) -> TSNode; + #[doc = " Create a shallow copy of the syntax tree. This is very fast."] + #[doc = ""] + #[doc = " You need to copy a syntax tree in order to use it on more than one thread at"] + #[doc = " a time, as syntax trees are not thread safe."] + pub fn ts_tree_copy(self_: *const TSTree) -> *mut TSTree; } extern "C" { - pub fn ts_tree_edit(arg1: *mut TSTree, arg2: *const TSInputEdit); + #[doc = " Delete the syntax tree, freeing all of the memory that it used."] + pub fn ts_tree_delete(self_: *mut TSTree); } extern "C" { - pub fn ts_tree_get_changed_ranges( - arg1: *const TSTree, - arg2: *const TSTree, - arg3: *mut u32, - ) -> *mut TSRange; -} -extern "C" { - pub fn ts_tree_print_dot_graph(arg1: *const TSTree, arg2: *mut FILE); + #[doc = " Get the root node of the syntax tree."] + pub fn ts_tree_root_node(self_: *const TSTree) -> TSNode; } extern "C" { + #[doc = " Get the language that was used to parse the syntax tree."] pub fn ts_tree_language(arg1: *const TSTree) -> *const TSLanguage; } extern "C" { - pub fn ts_node_start_byte(arg1: TSNode) -> u32; + #[doc = " Edit the syntax tree to keep it in sync with source code that has been"] + #[doc = " edited."] + #[doc = ""] + #[doc = " You must describe the edit both in terms of byte offsets and in terms of"] + #[doc = " (row, column) coordinates."] + pub fn ts_tree_edit(self_: *mut TSTree, edit: *const TSInputEdit); } extern "C" { - pub fn ts_node_start_point(arg1: TSNode) -> TSPoint; + #[doc = " Compare a new syntax tree to a previous syntax tree representing the same"] + #[doc = " document, returning an array of ranges whose syntactic structure has changed."] + #[doc = ""] + #[doc = " For this to work correctly, the old syntax tree must have been edited such"] + #[doc = " that its ranges match up to the new tree. Generally, you\'ll want to call"] + #[doc = " this function right after calling one of the `ts_parser_parse` functions,"] + #[doc = " passing in the new tree that was returned from `ts_parser_parse` and the old"] + #[doc = " tree that was passed as a parameter."] + #[doc = ""] + #[doc = " The returned array is allocated using `malloc` and the caller is responsible"] + #[doc = " for freeing it using `free`. The length of the array will be written to the"] + #[doc = " given `length` pointer."] + pub fn ts_tree_get_changed_ranges( + self_: *const TSTree, + old_tree: *const TSTree, + length: *mut u32, + ) -> *mut TSRange; } extern "C" { - pub fn ts_node_end_byte(arg1: TSNode) -> u32; -} -extern "C" { - pub fn ts_node_end_point(arg1: TSNode) -> TSPoint; -} -extern "C" { - pub fn ts_node_symbol(arg1: TSNode) -> TSSymbol; + #[doc = " Write a DOT graph describing the syntax tree to the given file."] + pub fn ts_tree_print_dot_graph(arg1: *const TSTree, arg2: *mut FILE); } extern "C" { + #[doc = " Get the node\'s type as a null-terminated string."] pub fn ts_node_type(arg1: TSNode) -> *const ::std::os::raw::c_char; } extern "C" { + #[doc = " Get the node\'s type as a numerical id."] + pub fn ts_node_symbol(arg1: TSNode) -> TSSymbol; +} +extern "C" { + #[doc = " Get the node\'s start byte."] + pub fn ts_node_start_byte(arg1: TSNode) -> u32; +} +extern "C" { + #[doc = " Get the node\'s start position in terms of rows and columns."] + pub fn ts_node_start_point(arg1: TSNode) -> TSPoint; +} +extern "C" { + #[doc = " Get the node\'s end byte."] + pub fn ts_node_end_byte(arg1: TSNode) -> u32; +} +extern "C" { + #[doc = " Get the node\'s end position in terms of rows and columns."] + pub fn ts_node_end_point(arg1: TSNode) -> TSPoint; +} +extern "C" { + #[doc = " Get an S-expression representing the node as a string."] + #[doc = ""] + #[doc = " This string is allocated with `malloc` and the caller is responsible for"] + #[doc = " freeing it using `free`."] pub fn ts_node_string(arg1: TSNode) -> *mut ::std::os::raw::c_char; } extern "C" { - pub fn ts_node_eq(arg1: TSNode, arg2: TSNode) -> bool; -} -extern "C" { + #[doc = " Check if the node is null. Functions like `ts_node_child` and"] + #[doc = " `ts_node_next_sibling` will return a null node to indicate that no such node"] + #[doc = " was found."] pub fn ts_node_is_null(arg1: TSNode) -> bool; } extern "C" { + #[doc = " Check if the node is *named*. Named nodes correspond to named rules in the"] + #[doc = " grammar, whereas *anonymous* nodes correspond to string literals in the"] + #[doc = " grammar."] pub fn ts_node_is_named(arg1: TSNode) -> bool; } extern "C" { + #[doc = " Check if the node is *missing*. Missing nodes are inserted by the parser in"] + #[doc = " order to recover from certain kinds of syntax errors."] pub fn ts_node_is_missing(arg1: TSNode) -> bool; } extern "C" { + #[doc = " Check if the node is *missing*. Missing nodes are inserted by the parser in"] + #[doc = " order to recover from certain kinds of syntax errors."] + pub fn ts_node_is_extra(arg1: TSNode) -> bool; +} +extern "C" { + #[doc = " Check if a syntax node has been edited."] pub fn ts_node_has_changes(arg1: TSNode) -> bool; } extern "C" { + #[doc = " Check if the node is a syntax error or contains any syntax errors."] pub fn ts_node_has_error(arg1: TSNode) -> bool; } extern "C" { + #[doc = " Get the node\'s immediate parent."] pub fn ts_node_parent(arg1: TSNode) -> TSNode; } extern "C" { + #[doc = " Get the node\'s child at the given index, where zero represents the first"] + #[doc = " child."] pub fn ts_node_child(arg1: TSNode, arg2: u32) -> TSNode; } extern "C" { - pub fn ts_node_child_by_field_id(arg1: TSNode, arg2: TSFieldId) -> TSNode; -} -extern "C" { - pub fn ts_node_child_by_field_name( - arg1: TSNode, - arg2: *const ::std::os::raw::c_char, - arg3: u32, - ) -> TSNode; -} -extern "C" { - pub fn ts_node_named_child(arg1: TSNode, arg2: u32) -> TSNode; -} -extern "C" { + #[doc = " Get the node\'s number of children."] pub fn ts_node_child_count(arg1: TSNode) -> u32; } extern "C" { + #[doc = " Get the node\'s *named* child at the given index."] + #[doc = ""] + #[doc = " See also `ts_node_is_named`."] + pub fn ts_node_named_child(arg1: TSNode, arg2: u32) -> TSNode; +} +extern "C" { + #[doc = " Get the node\'s number of *named* children."] + #[doc = ""] + #[doc = " See also `ts_node_is_named`."] pub fn ts_node_named_child_count(arg1: TSNode) -> u32; } extern "C" { - pub fn ts_node_next_sibling(arg1: TSNode) -> TSNode; + #[doc = " Get the node\'s child with the given field name."] + pub fn ts_node_child_by_field_name( + self_: TSNode, + field_name: *const ::std::os::raw::c_char, + field_name_length: u32, + ) -> TSNode; } extern "C" { - pub fn ts_node_next_named_sibling(arg1: TSNode) -> TSNode; + #[doc = " Get the node\'s child with the given numerical field id."] + #[doc = ""] + #[doc = " You can convert a field name to an id using the"] + #[doc = " `ts_language_field_id_for_name` function."] + pub fn ts_node_child_by_field_id(arg1: TSNode, arg2: TSFieldId) -> TSNode; +} +extern "C" { + #[doc = " Get the node\'s next / previous sibling."] + pub fn ts_node_next_sibling(arg1: TSNode) -> TSNode; } extern "C" { pub fn ts_node_prev_sibling(arg1: TSNode) -> TSNode; } +extern "C" { + #[doc = " Get the node\'s next / previous *named* sibling."] + pub fn ts_node_next_named_sibling(arg1: TSNode) -> TSNode; +} extern "C" { pub fn ts_node_prev_named_sibling(arg1: TSNode) -> TSNode; } extern "C" { + #[doc = " Get the node\'s first child that extends beyond the given byte offset."] pub fn ts_node_first_child_for_byte(arg1: TSNode, arg2: u32) -> TSNode; } extern "C" { + #[doc = " Get the node\'s first named child that extends beyond the given byte offset."] pub fn ts_node_first_named_child_for_byte(arg1: TSNode, arg2: u32) -> TSNode; } extern "C" { + #[doc = " Get the smallest node within this node that spans the given range of bytes"] + #[doc = " or (row, column) positions."] pub fn ts_node_descendant_for_byte_range(arg1: TSNode, arg2: u32, arg3: u32) -> TSNode; } -extern "C" { - pub fn ts_node_named_descendant_for_byte_range(arg1: TSNode, arg2: u32, arg3: u32) -> TSNode; -} extern "C" { pub fn ts_node_descendant_for_point_range(arg1: TSNode, arg2: TSPoint, arg3: TSPoint) -> TSNode; } +extern "C" { + #[doc = " Get the smallest named node within this node that spans the given range of"] + #[doc = " bytes or (row, column) positions."] + pub fn ts_node_named_descendant_for_byte_range(arg1: TSNode, arg2: u32, arg3: u32) -> TSNode; +} extern "C" { pub fn ts_node_named_descendant_for_point_range( arg1: TSNode, @@ -283,65 +457,118 @@ extern "C" { ) -> TSNode; } extern "C" { + #[doc = " Edit the node to keep it in-sync with source code that has been edited."] + #[doc = ""] + #[doc = " This function is only rarely needed. When you edit a syntax tree with the"] + #[doc = " `ts_tree_edit` function, all of the nodes that you retrieve from the tree"] + #[doc = " afterward will already reflect the edit. You only need to use `ts_node_edit`"] + #[doc = " when you have a `TSNode` instance that you want to keep and continue to use"] + #[doc = " after an edit."] pub fn ts_node_edit(arg1: *mut TSNode, arg2: *const TSInputEdit); } extern "C" { + #[doc = " Check if two nodes are identical."] + pub fn ts_node_eq(arg1: TSNode, arg2: TSNode) -> bool; +} +extern "C" { + #[doc = " Create a new tree cursor starting from the given node."] + #[doc = ""] + #[doc = " A tree cursor allows you to walk a syntax tree more efficiently than is"] + #[doc = " possible using the `TSNode` functions. It is a mutable object that is always"] + #[doc = " on a certain syntax node, and can be moved imperatively to different nodes."] pub fn ts_tree_cursor_new(arg1: TSNode) -> TSTreeCursor; } extern "C" { + #[doc = " Delete a tree cursor, freeing all of the memory that it used."] pub fn ts_tree_cursor_delete(arg1: *mut TSTreeCursor); } extern "C" { + #[doc = " Re-initialize a tree cursor to start at a different ndoe."] pub fn ts_tree_cursor_reset(arg1: *mut TSTreeCursor, arg2: TSNode); } extern "C" { + #[doc = " Get the tree cursor\'s current node."] pub fn ts_tree_cursor_current_node(arg1: *const TSTreeCursor) -> TSNode; } extern "C" { - pub fn ts_tree_cursor_current_field_id(arg1: *const TSTreeCursor) -> TSFieldId; -} -extern "C" { + #[doc = " Get the field name of the tree cursor\'s current node."] + #[doc = ""] + #[doc = " This returns `NULL` if the current node doesn\'t have a field."] + #[doc = " See also `ts_node_child_by_field_name`."] pub fn ts_tree_cursor_current_field_name( arg1: *const TSTreeCursor, ) -> *const ::std::os::raw::c_char; } extern "C" { + #[doc = " Get the field name of the tree cursor\'s current node."] + #[doc = ""] + #[doc = " This returns zero if the current node doesn\'t have a field."] + #[doc = " See also `ts_node_child_by_field_id`, `ts_language_field_id_for_name`."] + pub fn ts_tree_cursor_current_field_id(arg1: *const TSTreeCursor) -> TSFieldId; +} +extern "C" { + #[doc = " Move the cursor to the parent of its current node."] + #[doc = ""] + #[doc = " This returns `true` if the cursor successfully moved, and returns `false`"] + #[doc = " if there was no parent node (the cursor was already on the root node)."] pub fn ts_tree_cursor_goto_parent(arg1: *mut TSTreeCursor) -> bool; } extern "C" { + #[doc = " Move the cursor to the next sibling of its current node."] + #[doc = ""] + #[doc = " This returns `true` if the cursor successfully moved, and returns `false`"] + #[doc = " if there was no next sibling node."] pub fn ts_tree_cursor_goto_next_sibling(arg1: *mut TSTreeCursor) -> bool; } extern "C" { + #[doc = " Move the cursor to the first schild of its current node."] + #[doc = ""] + #[doc = " This returns `true` if the cursor successfully moved, and returns `false`"] + #[doc = " if there were no children."] pub fn ts_tree_cursor_goto_first_child(arg1: *mut TSTreeCursor) -> bool; } extern "C" { + #[doc = " Move the cursor to the first schild of its current node that extends beyond"] + #[doc = " the given byte offset."] + #[doc = ""] + #[doc = " This returns the index of the child node if one was found, and returns -1"] + #[doc = " if no such child was found."] pub fn ts_tree_cursor_goto_first_child_for_byte(arg1: *mut TSTreeCursor, arg2: u32) -> i64; } extern "C" { + pub fn ts_tree_cursor_copy(arg1: *const TSTreeCursor) -> TSTreeCursor; +} +extern "C" { + #[doc = " Get the number of distinct node types in the language."] pub fn ts_language_symbol_count(arg1: *const TSLanguage) -> u32; } extern "C" { + #[doc = " Get a node type string for the given numerical id."] pub fn ts_language_symbol_name( arg1: *const TSLanguage, arg2: TSSymbol, ) -> *const ::std::os::raw::c_char; } extern "C" { + #[doc = " Get the numerical id for the given node type string."] pub fn ts_language_symbol_for_name( arg1: *const TSLanguage, arg2: *const ::std::os::raw::c_char, ) -> TSSymbol; } extern "C" { + #[doc = " Get the number of distinct field names in the language."] pub fn ts_language_field_count(arg1: *const TSLanguage) -> u32; } extern "C" { + #[doc = " Get the field name string for the given numerical id."] pub fn ts_language_field_name_for_id( arg1: *const TSLanguage, arg2: TSFieldId, ) -> *const ::std::os::raw::c_char; } extern "C" { + #[doc = " Get the numerical id for the given field name string."] pub fn ts_language_field_id_for_name( arg1: *const TSLanguage, arg2: *const ::std::os::raw::c_char, @@ -349,9 +576,18 @@ extern "C" { ) -> TSFieldId; } extern "C" { + #[doc = " Check whether the given node type id belongs to named nodes, anonymous nodes,"] + #[doc = " or a hidden nodes."] + #[doc = ""] + #[doc = " See also `ts_node_is_named`. Hidden nodes are never returned from the API."] pub fn ts_language_symbol_type(arg1: *const TSLanguage, arg2: TSSymbol) -> TSSymbolType; } extern "C" { + #[doc = " Get the ABI version number for this language. This version number is used"] + #[doc = " to ensure that languages were generated by a compatible version of"] + #[doc = " Tree-sitter."] + #[doc = ""] + #[doc = " See also `ts_parser_set_language`."] pub fn ts_language_version(arg1: *const TSLanguage) -> u32; } diff --git a/lib/binding_rust/lib.rs b/lib/binding_rust/lib.rs index 74b275a0..ba2d01f7 100644 --- a/lib/binding_rust/lib.rs +++ b/lib/binding_rust/lib.rs @@ -469,6 +469,10 @@ impl<'tree> Node<'tree> { unsafe { ffi::ts_node_is_named(self.0) } } + pub fn is_extra(&self) -> bool { + unsafe { ffi::ts_node_is_extra(self.0) } + } + pub fn has_changes(&self) -> bool { unsafe { ffi::ts_node_has_changes(self.0) } } diff --git a/lib/include/tree_sitter/api.h b/lib/include/tree_sitter/api.h index b07f929f..9375db8b 100644 --- a/lib/include/tree_sitter/api.h +++ b/lib/include/tree_sitter/api.h @@ -408,6 +408,12 @@ bool ts_node_is_named(TSNode); */ bool ts_node_is_missing(TSNode); +/** + * Check if the node is *missing*. Missing nodes are inserted by the parser in + * order to recover from certain kinds of syntax errors. + */ +bool ts_node_is_extra(TSNode); + /** * Check if a syntax node has been edited. */ @@ -593,7 +599,7 @@ bool ts_tree_cursor_goto_first_child(TSTreeCursor *); * if no such child was found. */ int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *, uint32_t); - + TSTreeCursor ts_tree_cursor_copy(const TSTreeCursor *); /**********************/ diff --git a/lib/src/node.c b/lib/src/node.c index 4820666b..355585f2 100644 --- a/lib/src/node.c +++ b/lib/src/node.c @@ -435,6 +435,10 @@ bool ts_node_is_null(TSNode self) { return self.id == 0; } +bool ts_node_is_extra(TSNode self) { + return ts_subtree_extra(ts_node__subtree(self)); +} + bool ts_node_is_named(TSNode self) { return ts_node__alias(&self) ? ts_language_symbol_metadata(self.tree->language, ts_node__alias(&self)).named