fix(lib): reset parser options after use#4355
Conversation
|
A question based on the way the failing tests are set up; is this behavior actually intended? |
Reading through the failing test, I believe it is intended for state to persist between calls to
Thought I had a fix, but the neovim reproducer still failsThat being said, as far as I can tell there is no intention (or reason to) preserve the progress callback between calls. That does seem like a footgun. I tried the following change to this patch with the tree-sitter test suite as well as the neovim reproducer and both are running clean: diff --git a/lib/src/parser.c b/lib/src/parser.c
index 71cf7bdb..49c4d440 100644
--- a/lib/src/parser.c
+++ b/lib/src/parser.c
@@ -2238,9 +2238,8 @@ TSTree *ts_parser_parse_with_options(
self->parse_options = parse_options;
self->parse_state.payload = parse_options.payload;
TSTree *result = ts_parser_parse(self, old_tree, input);
- // Reset parser state & options before further parse calls.
- self->parse_options = (TSParseOptions) {0};
- self->parse_state = (TSParseState) {0};
+ // Reset callback before further parse calls
+ self->parse_options.progress_callback = NULL;
return result;
}(Please double check me though! It's easy to make mistakes this late at night 😅) Reading through the original PR that added Lines 314 to 336 in b341073 I'm not sure what the original motivation behind this is. Probably safe to remove? |
|
Nice! Thanks, that makes a lot of sense. So the patch you gave does work, or it still fails the neovim reproducer? Also, if we clear callbacks, should the patch be changed to the following? diff --git a/lib/src/parser.c b/lib/src/parser.c
index adcdf8d0..0429ce9a 100644
--- a/lib/src/parser.c
+++ b/lib/src/parser.c
@@ -1540,7 +1540,7 @@ static bool ts_parser__check_progress(TSParser *self, Subtree *lookahead, const
if (self->operation_count >= OP_COUNT_PER_PARSER_TIMEOUT_CHECK) {
self->operation_count = 0;
}
- if (self->parse_options.progress_callback && position != NULL) {
+ if (position != NULL) {
self->parse_state.current_byte_offset = *position;
self->parse_state.has_error = self->has_error;
}
@@ -2238,6 +2238,7 @@ TSTree *ts_parser_parse_with_options(
self->parse_options = parse_options;
self->parse_state.payload = parse_options.payload;
TSTree *result = ts_parser_parse(self, old_tree, input);
+ self->parse_options = (TSParseOptions) {0};
return result;
}that way the parser state is kept consistent even when parsing without a callback (not sure if that is strictly necessary) |
I believe it still fails the neovim reproducer. I was swapping between testing changes to neovim and tree-sitter locally, and I thought the reproducer passed (running
That seems correct, but I'm not 100% sure. I'll do some more testing locally to check it out :) |
|
You need to |
|
@ribru17 your latest patch is working for me locally! Mind pushing it up? |
**Problem:** After `ts_parser_parse_with_options()`, the parser options are still stored in the parser object, meaning that a successive call to `ts_parser_parse()` will actually behave like `ts_parser_parse_with_options()`, which is not obvious and can have unintended consequences. **Solution:** Reset to empty options state after `ts_parser_parse_with_options()`.
|
Successfully created backport PR for |
Problem: After
ts_parser_parse_with_options(), the parser options are still stored in the parser object, meaning that a successive call tots_parser_parse()will actually behave likets_parser_parse_with_options(), which is not obvious and can have unintended consequences.Solution: Reset to empty options state after
ts_parser_parse_with_options().See neovim/neovim#33437 for real life example