When editing, properly invalidate trees that depend on get_column
This commit is contained in:
parent
e29d3714f7
commit
a40045a419
8 changed files with 136 additions and 35 deletions
|
|
@ -166,7 +166,8 @@ static inline bool ts_subtree_can_inline(Length padding, Length size, uint32_t l
|
|||
|
||||
Subtree ts_subtree_new_leaf(
|
||||
SubtreePool *pool, TSSymbol symbol, Length padding, Length size,
|
||||
uint32_t lookahead_bytes, TSStateId parse_state, bool has_external_tokens,
|
||||
uint32_t lookahead_bytes, TSStateId parse_state,
|
||||
bool has_external_tokens, bool depends_on_column,
|
||||
bool is_keyword, const TSLanguage *language
|
||||
) {
|
||||
TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol);
|
||||
|
|
@ -213,6 +214,7 @@ Subtree ts_subtree_new_leaf(
|
|||
.fragile_right = false,
|
||||
.has_changes = false,
|
||||
.has_external_tokens = has_external_tokens,
|
||||
.depends_on_column = depends_on_column,
|
||||
.is_missing = false,
|
||||
.is_keyword = is_keyword,
|
||||
{{.first_leaf = {.symbol = 0, .parse_state = 0}}}
|
||||
|
|
@ -245,7 +247,7 @@ Subtree ts_subtree_new_error(
|
|||
) {
|
||||
Subtree result = ts_subtree_new_leaf(
|
||||
pool, ts_builtin_sym_error, padding, size, bytes_scanned,
|
||||
parse_state, false, false, language
|
||||
parse_state, false, false, false, language
|
||||
);
|
||||
SubtreeHeapData *data = (SubtreeHeapData *)result.ptr;
|
||||
data->fragile_left = true;
|
||||
|
|
@ -378,6 +380,7 @@ void ts_subtree_summarize_children(
|
|||
self.ptr->repeat_depth = 0;
|
||||
self.ptr->node_count = 1;
|
||||
self.ptr->has_external_tokens = false;
|
||||
self.ptr->depends_on_column = false;
|
||||
self.ptr->dynamic_precedence = 0;
|
||||
|
||||
uint32_t structural_index = 0;
|
||||
|
|
@ -388,6 +391,13 @@ void ts_subtree_summarize_children(
|
|||
for (uint32_t i = 0; i < self.ptr->child_count; i++) {
|
||||
Subtree child = children[i];
|
||||
|
||||
if (
|
||||
self.ptr->size.extent.row == 0 &&
|
||||
ts_subtree_depends_on_column(child)
|
||||
) {
|
||||
self.ptr->depends_on_column = true;
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
self.ptr->padding = ts_subtree_padding(child);
|
||||
self.ptr->size = ts_subtree_size(child);
|
||||
|
|
@ -545,7 +555,7 @@ Subtree ts_subtree_new_missing_leaf(
|
|||
) {
|
||||
Subtree result = ts_subtree_new_leaf(
|
||||
pool, symbol, padding, length_zero(), 0,
|
||||
0, false, false, language
|
||||
0, false, false, false, language
|
||||
);
|
||||
if (result.data.is_inline) {
|
||||
result.data.is_missing = true;
|
||||
|
|
@ -670,6 +680,7 @@ Subtree ts_subtree_edit(Subtree self, const TSInputEdit *edit, SubtreePool *pool
|
|||
Edit edit = entry.edit;
|
||||
bool is_noop = edit.old_end.bytes == edit.start.bytes && edit.new_end.bytes == edit.start.bytes;
|
||||
bool is_pure_insertion = edit.old_end.bytes == edit.start.bytes;
|
||||
bool invalidate_first_row = ts_subtree_depends_on_column(*entry.tree);
|
||||
|
||||
Length size = ts_subtree_size(*entry.tree);
|
||||
Length padding = ts_subtree_padding(*entry.tree);
|
||||
|
|
@ -733,6 +744,7 @@ Subtree ts_subtree_edit(Subtree self, const TSInputEdit *edit, SubtreePool *pool
|
|||
data->fragile_right = false;
|
||||
data->has_changes = false;
|
||||
data->has_external_tokens = false;
|
||||
data->depends_on_column = false;
|
||||
data->is_missing = result.data.is_missing;
|
||||
data->is_keyword = result.data.is_keyword;
|
||||
result.ptr = data;
|
||||
|
|
@ -755,9 +767,18 @@ Subtree ts_subtree_edit(Subtree self, const TSInputEdit *edit, SubtreePool *pool
|
|||
// If this child ends before the edit, it is not affected.
|
||||
if (child_right.bytes + ts_subtree_lookahead_bytes(*child) < edit.start.bytes) continue;
|
||||
|
||||
// If this child starts after the edit, then we're done processing children.
|
||||
if (child_left.bytes > edit.old_end.bytes ||
|
||||
(child_left.bytes == edit.old_end.bytes && child_size.bytes > 0 && i > 0)) break;
|
||||
// Keep editing child nodes until a node is reached that starts after the edit.
|
||||
// Also, if this node's validity depends on its column position, then continue
|
||||
// invaliditing child nodes until reaching a line break.
|
||||
if ((
|
||||
(child_left.bytes > edit.old_end.bytes) ||
|
||||
(child_left.bytes == edit.old_end.bytes && child_size.bytes > 0 && i > 0)
|
||||
) && (
|
||||
!invalidate_first_row ||
|
||||
child_left.extent.row > entry.tree->ptr->padding.extent.row
|
||||
)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Transform edit into the child's coordinate space.
|
||||
Edit child_edit = {
|
||||
|
|
@ -775,8 +796,10 @@ Subtree ts_subtree_edit(Subtree self, const TSInputEdit *edit, SubtreePool *pool
|
|||
// Interpret all inserted text as applying to the *first* child that touches the edit.
|
||||
// Subsequent children are only never have any text inserted into them; they are only
|
||||
// shrunk to compensate for the edit.
|
||||
if (child_right.bytes > edit.start.bytes ||
|
||||
(child_right.bytes == edit.start.bytes && is_pure_insertion)) {
|
||||
if (
|
||||
child_right.bytes > edit.start.bytes ||
|
||||
(child_right.bytes == edit.start.bytes && is_pure_insertion)
|
||||
) {
|
||||
edit.new_end = edit.start;
|
||||
}
|
||||
|
||||
|
|
@ -981,12 +1004,14 @@ void ts_subtree__print_dot_graph(const Subtree *self, uint32_t start_offset,
|
|||
"state: %d\n"
|
||||
"error-cost: %u\n"
|
||||
"has-changes: %u\n"
|
||||
"depends-on-column: %u\n"
|
||||
"repeat-depth: %u\n"
|
||||
"lookahead-bytes: %u",
|
||||
start_offset, end_offset,
|
||||
ts_subtree_parse_state(*self),
|
||||
ts_subtree_error_cost(*self),
|
||||
ts_subtree_has_changes(*self),
|
||||
ts_subtree_depends_on_column(*self),
|
||||
ts_subtree_repeat_depth(*self),
|
||||
ts_subtree_lookahead_bytes(*self)
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue