Change the TSInputEdit struct to work with old/new start and end positions

This commit is contained in:
Max Brunsfeld 2018-05-17 11:14:51 -07:00
parent 95be6e3bee
commit 074c051094
4 changed files with 81 additions and 69 deletions

View file

@ -57,11 +57,11 @@ typedef struct {
typedef struct {
uint32_t start_byte;
uint32_t bytes_removed;
uint32_t bytes_added;
uint32_t old_end_byte;
uint32_t new_end_byte;
TSPoint start_point;
TSPoint extent_removed;
TSPoint extent_added;
TSPoint old_end_point;
TSPoint new_end_point;
} TSInputEdit;
typedef struct {

View file

@ -13,8 +13,8 @@
typedef struct {
Length start;
Length added;
Length removed;
Length old_end;
Length new_end;
} Edit;
TSStateId TS_TREE_STATE_NONE = USHRT_MAX;
@ -490,22 +490,23 @@ const Subtree *ts_subtree_invalidate_lookahead(const Subtree *self, uint32_t edi
}
const Subtree *ts_subtree__edit(const Subtree *self, Edit edit, SubtreePool *pool) {
Length new_end = length_add(edit.start, edit.added);
Length old_end = length_add(edit.start, edit.removed);
Subtree *result = ts_subtree_make_mut(pool, self);
result->has_changes = true;
if (old_end.bytes <= result->padding.bytes) {
result->padding = length_add(new_end, length_sub(result->padding, old_end));
bool pure_insertion = edit.old_end.bytes == edit.start.bytes;
if (edit.old_end.bytes <= result->padding.bytes) {
result->padding = length_add(edit.new_end, length_sub(result->padding, edit.old_end));
} else if (edit.start.bytes < result->padding.bytes) {
result->size = length_sub(result->size, length_sub(old_end, result->padding));
result->padding = new_end;
} else if (edit.start.bytes == result->padding.bytes && edit.removed.bytes == 0) {
result->padding = length_add(result->padding, edit.added);
result->size = length_sub(result->size, length_sub(edit.old_end, result->padding));
result->padding = edit.new_end;
} else if (edit.start.bytes == result->padding.bytes && pure_insertion) {
result->padding = edit.new_end;
} else {
Length new_total_size = length_add(new_end, length_sub(ts_subtree_total_size(result), old_end));
result->size = length_sub(new_total_size, result->padding);
result->size = length_add(
length_sub(edit.new_end, result->padding),
length_sub(result->size, length_sub(edit.old_end, result->padding))
);
}
Length child_left, child_right = length_zero();
@ -515,27 +516,23 @@ const Subtree *ts_subtree__edit(const Subtree *self, Edit edit, SubtreePool *poo
child_left = child_right;
child_right = length_add(child_left, child_size);
if (child_left.bytes > old_end.bytes ||
(child_left.bytes == old_end.bytes && child_size.bytes > 0 && i > 0)) break;
if (child_left.bytes > edit.old_end.bytes ||
(child_left.bytes == edit.old_end.bytes && child_size.bytes > 0 && i > 0)) break;
if (child_right.bytes > edit.start.bytes ||
(child_right.bytes == edit.start.bytes && edit.removed.bytes == 0)) {
(child_right.bytes == edit.start.bytes && pure_insertion)) {
Edit child_edit = {
.start = length_sub(edit.start, child_left),
.added = edit.added,
.removed = edit.removed,
.old_end = length_sub(edit.old_end, child_left),
.new_end = length_sub(edit.new_end, child_left),
};
if (edit.start.bytes < child_left.bytes) {
child_edit.start = length_zero();
}
if (edit.start.bytes < child_left.bytes) child_edit.start = length_zero();
if (edit.old_end.bytes < child_left.bytes) child_edit.old_end = length_zero();
if (edit.new_end.bytes < child_left.bytes) child_edit.new_end = length_zero();
if (edit.old_end.bytes > child_right.bytes) child_edit.old_end = child_size;
if (old_end.bytes > child_right.bytes) {
child_edit.removed = length_sub(child_size, child_edit.start);
}
edit.added = length_zero();
edit.removed = length_sub(edit.removed, child_edit.removed);
edit.new_end = edit.start;
*child = ts_subtree__edit(*child, child_edit, pool);
} else if (child_left.bytes <= edit.start.bytes) {
@ -549,8 +546,8 @@ const Subtree *ts_subtree__edit(const Subtree *self, Edit edit, SubtreePool *poo
const Subtree *ts_subtree_edit(const Subtree *self, const TSInputEdit *edit, SubtreePool *pool) {
return ts_subtree__edit(self, (Edit) {
.start = {edit->start_byte, edit->start_point},
.added = {edit->bytes_added, edit->extent_added},
.removed = {edit->bytes_removed, edit->extent_removed},
.old_end = {edit->old_end_byte, edit->old_end_point},
.new_end = {edit->new_end_byte, edit->new_end_point},
}, pool);
}

View file

@ -1,5 +1,6 @@
#include "helpers/spy_input.h"
#include "helpers/encoding_helpers.h"
#include "runtime/point.h"
#include <string.h>
#include <algorithm>
#include <assert.h>
@ -20,6 +21,14 @@ SpyInput::~SpyInput() {
delete[] buffer;
}
static TSPoint operator+(TSPoint a, TSPoint b) {
if (b.row > 0) {
return TSPoint {a.row + b.row, b.column};
} else {
return TSPoint {a.row, a.column + b.column};
}
}
static void add_byte_range(vector<pair<uint32_t, uint32_t>> *ranges,
uint32_t start, uint32_t count) {
uint32_t end = start + count;
@ -112,11 +121,11 @@ TSInputEdit SpyInput::replace(size_t start_byte, size_t bytes_removed, string te
undo_stack.push_back(SpyInputEdit{start_byte, bytes_added, swap.first});
TSInputEdit result = {};
result.start_byte = start_byte;
result.bytes_added = bytes_added;
result.bytes_removed = bytes_removed;
result.old_end_byte = start_byte + bytes_removed;
result.new_end_byte = start_byte + bytes_added;
result.start_point = swap.second;
result.extent_removed = get_extent(swap.first);
result.extent_added = get_extent(text);
result.old_end_point = result.start_point + get_extent(swap.first);
result.new_end_point = result.start_point + get_extent(text);
return result;
}
@ -126,11 +135,11 @@ TSInputEdit SpyInput::undo() {
auto swap = swap_substr(entry.start_byte, entry.bytes_removed, entry.text_inserted);
TSInputEdit result;
result.start_byte = entry.start_byte;
result.bytes_removed = entry.bytes_removed;
result.bytes_added = entry.text_inserted.size();
result.old_end_byte = entry.start_byte + entry.bytes_removed;
result.new_end_byte = entry.start_byte + entry.text_inserted.size();
result.start_point = swap.second;
result.extent_removed = get_extent(swap.first);
result.extent_added = get_extent(entry.text_inserted);
result.old_end_point = result.start_point + get_extent(swap.first);
result.new_end_point = result.start_point + get_extent(entry.text_inserted);
return result;
}

View file

@ -202,11 +202,11 @@ describe("Subtree", []() {
it("does not mutate the argument", [&]() {
TSInputEdit edit;
edit.start_byte = 1;
edit.bytes_removed = 0;
edit.bytes_added = 1;
edit.old_end_byte = 1;
edit.new_end_byte = 2;
edit.start_point = {0, 1};
edit.extent_removed = {0, 0};
edit.extent_added = {0, 1};
edit.old_end_point = {0, 1};
edit.new_end_point = {0, 2};
ts_subtree_retain(tree);
const Subtree *new_tree = ts_subtree_edit(tree, &edit, &pool);
@ -232,11 +232,12 @@ describe("Subtree", []() {
it("resizes the padding of the tree and its leftmost descendants", [&]() {
TSInputEdit edit;
edit.start_byte = 1;
edit.bytes_removed = 0;
edit.bytes_added = 1;
edit.old_end_byte = 1;
edit.new_end_byte = 2;
edit.start_point = {0, 1};
edit.extent_removed = {0, 0};
edit.extent_added = {0, 1};
edit.old_end_point = {0, 1};
edit.new_end_point = {0, 2};
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
@ -258,11 +259,12 @@ describe("Subtree", []() {
it("shrinks the content to compensate for the expanded padding", [&]() {
TSInputEdit edit;
edit.start_byte = 1;
edit.bytes_removed = 3;
edit.bytes_added = 4;
edit.old_end_byte = 4;
edit.new_end_byte = 5;
edit.start_point = {0, 1};
edit.extent_removed = {0, 3};
edit.extent_added = {0, 4};
edit.old_end_point = {0, 4};
edit.new_end_point = {0, 5};
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
@ -280,11 +282,12 @@ describe("Subtree", []() {
it("expands the tree's padding", [&]() {
TSInputEdit edit;
edit.start_byte = 2;
edit.bytes_removed = 0;
edit.bytes_added = 2;
edit.old_end_byte = 2;
edit.new_end_byte = 4;
edit.start_point = {0, 2};
edit.extent_removed = {0, 0};
edit.extent_added = {0, 2};
edit.old_end_point = {0, 2};
edit.new_end_point = {0, 4};
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
@ -304,11 +307,12 @@ describe("Subtree", []() {
it("resizes the content and not the padding", [&]() {
TSInputEdit edit;
edit.start_byte = 2;
edit.bytes_removed = 2;
edit.bytes_added = 5;
edit.old_end_byte = 4;
edit.new_end_byte = 7;
edit.start_point = {0, 2};
edit.extent_removed = {0, 2};
edit.extent_added = {0, 5};
edit.old_end_point = {0, 4};
edit.new_end_point = {0, 7};
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
@ -328,11 +332,12 @@ describe("Subtree", []() {
it("shrinks subsequent child nodes", [&]() {
TSInputEdit edit;
edit.start_byte = 1;
edit.bytes_removed = 10;
edit.bytes_added = 3;
edit.old_end_byte = 11;
edit.new_end_byte = 4;
edit.start_point = {0, 1};
edit.extent_removed = {0, 10};
edit.extent_added = {0, 3};
edit.old_end_point = {0, 11};
edit.new_end_point = {0, 4};
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
@ -361,11 +366,12 @@ describe("Subtree", []() {
TSInputEdit edit;
edit.start_byte = 6;
edit.bytes_removed = 1;
edit.bytes_added = 1;
edit.old_end_byte = 7;
edit.new_end_byte = 7;
edit.start_point = {0, 6};
edit.extent_removed = {0, 1};
edit.extent_added = {0, 1};
edit.old_end_point = {0, 7};
edit.new_end_point = {0, 7};
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);