Fix bugs in editing/reparsing

This commit is contained in:
Max Brunsfeld 2018-05-18 14:27:08 -07:00
parent 819b140701
commit 4da669ce8d
3 changed files with 92 additions and 13 deletions

View file

@ -52,7 +52,7 @@ tree.edit(InputEdit {
old_end_position: Point::new(0, 8),
new_end_position: Point::new(0, 14),
});
let new_tree = parser.parse_str(new_source_code, Some(tree));
let new_tree = parser.parse_str(new_source_code, Some(&tree));
```
### Text Input

View file

@ -123,7 +123,7 @@ impl Parser {
unsafe { ffi::ts_parser_set_logger(self.0, c_logger) };
}
pub fn parse_str(&mut self, input: &str, old_tree: Option<Tree>) -> Option<Tree> {
pub fn parse_str(&mut self, input: &str, old_tree: Option<&Tree>) -> Option<Tree> {
let mut input = FlatInput { bytes: input.as_bytes(), offset: 0};
self.parse_utf8(&mut input, old_tree)
}
@ -131,7 +131,7 @@ impl Parser {
pub fn parse_utf8<T: Utf8Input>(
&mut self,
input: &mut T,
old_tree: Option<Tree>,
old_tree: Option<&Tree>,
) -> Option<Tree> {
unsafe extern "C" fn read<T: Utf8Input>(
payload: *mut c_void,
@ -179,7 +179,7 @@ impl Parser {
pub fn parse_utf16<T: Utf16Input>(
&mut self,
input: &mut T,
old_tree: Option<Tree>,
old_tree: Option<&Tree>,
) -> Option<Tree> {
unsafe extern "C" fn read<T: Utf16Input>(
payload: *mut c_void,
@ -266,7 +266,7 @@ impl Clone for Tree {
}
}
impl<'a> Node<'a> {
impl<'tree> Node<'tree> {
fn new(node: ffi::TSNode) -> Option<Self> {
if node.id.is_null() {
None
@ -319,7 +319,7 @@ impl<'a> Node<'a> {
}
}
pub fn child(&self, i: u32) -> Option<Node> {
pub fn child(&self, i: u32) -> Option<Self> {
Self::new(unsafe { ffi::ts_node_child(self.0, i) })
}
@ -327,7 +327,7 @@ impl<'a> Node<'a> {
unsafe { ffi::ts_node_child_count(self.0) }
}
pub fn named_child(&self, i: u32) -> Option<Node> {
pub fn named_child<'a>(&'a self, i: u32) -> Option<Self> {
Self::new(unsafe { ffi::ts_node_named_child(self.0, i) })
}
@ -335,23 +335,23 @@ impl<'a> Node<'a> {
unsafe { ffi::ts_node_named_child_count(self.0) }
}
pub fn parent(&self) -> Option<Node> {
pub fn parent(&self) -> Option<Self> {
Self::new(unsafe { ffi::ts_node_parent(self.0) })
}
pub fn next_sibling(&self) -> Option<Node> {
pub fn next_sibling(&self) -> Option<Self> {
Self::new(unsafe { ffi::ts_node_next_sibling(self.0) })
}
pub fn prev_sibling(&self) -> Option<Node> {
pub fn prev_sibling(&self) -> Option<Self> {
Self::new(unsafe { ffi::ts_node_prev_sibling(self.0) })
}
pub fn next_named_sibling(&self) -> Option<Node> {
pub fn next_named_sibling(&self) -> Option<Self> {
Self::new(unsafe { ffi::ts_node_next_named_sibling(self.0) })
}
pub fn prev_named_sibling(&self) -> Option<Node> {
pub fn prev_named_sibling(&self) -> Option<Self> {
Self::new(unsafe { ffi::ts_node_prev_named_sibling(self.0) })
}
@ -413,6 +413,12 @@ impl<'a> Drop for TreeCursor<'a> {
}
}
impl Point {
pub fn new(row: u32, column: u32) -> Self {
Point { row, column }
}
}
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "({}, {})", self.row, self.column)
@ -577,4 +583,77 @@ mod tests {
assert_eq!(node1.child(0).unwrap(), node2.child(0).unwrap());
assert_ne!(node1.child(0).unwrap(), node2);
}
#[test]
fn test_editing() {
struct SpyInput {
bytes: &'static [u8],
offset: usize,
bytes_read: Vec<u8>,
}
impl Utf8Input for SpyInput {
fn read(&mut self) -> &[u8] {
if self.offset < self.bytes.len() {
let result = &self.bytes[self.offset..self.offset + 1];
self.bytes_read.extend(result.iter());
self.offset += 1;
result
} else {
&[]
}
}
fn seek(&mut self, byte: u32, _position: Point) {
self.offset = byte as usize;
}
}
let mut input = SpyInput {
bytes: "fn test(a: A, c: C) {}".as_bytes(),
offset: 0,
bytes_read: Vec::new(),
};
let mut parser = Parser::new();
parser.set_language(rust()).unwrap();
let mut tree = parser.parse_utf8(&mut input, None).unwrap();
let parameters_sexp = tree.root_node()
.named_child(0).unwrap()
.named_child(1).unwrap()
.to_sexp();
assert_eq!(
parameters_sexp,
"(parameters (parameter (identifier) (type_identifier)) (parameter (identifier) (type_identifier)))"
);
input.offset = 0;
input.bytes_read.clear();
input.bytes = "fn test(a: A, b: B, c: C) {}".as_bytes();
tree.edit(&InputEdit{
start_byte: 14,
old_end_byte: 14,
new_end_byte: 20,
start_position: Point::new(0, 14),
old_end_position: Point::new(0, 14),
new_end_position: Point::new(0, 20),
});
let tree = parser.parse_utf8(&mut input, Some(&tree)).unwrap();
let parameters_sexp = tree.root_node()
.named_child(0).unwrap()
.named_child(1).unwrap()
.to_sexp();
assert_eq!(
parameters_sexp,
"(parameters (parameter (identifier) (type_identifier)) (parameter (identifier) (type_identifier)) (parameter (identifier) (type_identifier)))"
);
let retokenized_content = String::from_utf8(input.bytes_read).unwrap();
assert!(retokenized_content.contains("b: B"));
assert!(!retokenized_content.contains("a: A"));
assert!(!retokenized_content.contains("c: C"));
assert!(!retokenized_content.contains("{}"));
}
}

2
vendor/tree-sitter vendored

@ -1 +1 @@
Subproject commit 9c1e82a7eac97767cee0469faa2722fd5753b065
Subproject commit 78f28b14ce519ba085ab7886c2fc19739f7f7da0