From 36c2b685b9ca74b90bf1e4ba590ea6579c915eef Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 4 Oct 2017 15:09:46 -0700 Subject: [PATCH] Always invalidate old chunk of text when parsing after an edit --- src/runtime/lexer.c | 3 +++ src/runtime/parser.c | 2 +- test/helpers/spy_input.cc | 2 +- test/helpers/spy_input.h | 2 +- test/runtime/document_test.cc | 35 ++++++++++++++++++++++++++++++++--- 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/runtime/lexer.c b/src/runtime/lexer.c index 599bea62..a165b8a6 100644 --- a/src/runtime/lexer.c +++ b/src/runtime/lexer.c @@ -132,6 +132,9 @@ static inline void ts_lexer__reset(Lexer *self, Length position) { void ts_lexer_set_input(Lexer *self, TSInput input) { self->input = input; + self->chunk = 0; + self->chunk_start = 0; + self->chunk_size = 0; ts_lexer__reset(self, length_zero()); } diff --git a/src/runtime/parser.c b/src/runtime/parser.c index 527b0a82..5a7dff20 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -17,7 +17,7 @@ if (self->lexer.logger.log || self->print_debugging_graphs) { \ snprintf(self->lexer.debug_buffer, TREE_SITTER_SERIALIZATION_BUFFER_SIZE, __VA_ARGS__); \ parser__log(self); \ - } \ + } #define LOG_STACK() \ if (self->print_debugging_graphs) { \ diff --git a/test/helpers/spy_input.cc b/test/helpers/spy_input.cc index ae7e9c1f..01554e85 100644 --- a/test/helpers/spy_input.cc +++ b/test/helpers/spy_input.cc @@ -9,9 +9,9 @@ using std::string; using std::vector; SpyInput::SpyInput(string content, size_t chars_per_chunk) : - chars_per_chunk(chars_per_chunk), buffer(nullptr), byte_offset(0), + chars_per_chunk(chars_per_chunk), content(content), encoding(TSInputEncodingUTF8), ranges_read({}) {} diff --git a/test/helpers/spy_input.h b/test/helpers/spy_input.h index 2a15ad9b..2de1a301 100644 --- a/test/helpers/spy_input.h +++ b/test/helpers/spy_input.h @@ -12,7 +12,6 @@ struct SpyInputEdit { }; class SpyInput { - uint32_t chars_per_chunk; char *buffer; uint32_t byte_offset; std::vector undo_stack; @@ -31,6 +30,7 @@ class SpyInput { TSInputEdit undo(); std::vector strings_read() const; + uint32_t chars_per_chunk; std::string content; TSInputEncoding encoding; std::vector> ranges_read; diff --git a/test/runtime/document_test.cc b/test/runtime/document_test.cc index 138264bb..7917a152 100644 --- a/test/runtime/document_test.cc +++ b/test/runtime/document_test.cc @@ -15,8 +15,6 @@ TSPoint point(size_t row, size_t column) { START_TEST - - describe("Document", [&]() { TSDocument *document; TSNode root; @@ -259,7 +257,7 @@ describe("Document", [&]() { before_each([&]() { ts_document_set_language(document, load_real_language("javascript")); - input = new SpyInput("{a: null};", 3); + input = new SpyInput("{a: null};\n", 3); ts_document_set_input(document, input->input()); ts_document_parse(document); assert_node_string_equals( @@ -313,6 +311,37 @@ describe("Document", [&]() { }))); }); + it("reports no changes when leading whitespace has changed (regression)", [&]() { + input->chars_per_chunk = 80; + + // Insert leading whitespace + auto ranges = get_invalidated_ranges_for_edit([&]() { + return input->replace(0, 0, "\n"); + }); + assert_node_string_equals( + ts_document_root_node(document), + "(program (expression_statement (object (pair (property_identifier) (null)))))"); + AssertThat(ranges, Equals(vector({}))); + + // Remove leading whitespace + ranges = get_invalidated_ranges_for_edit([&]() { + return input->undo(); + }); + assert_node_string_equals( + ts_document_root_node(document), + "(program (expression_statement (object (pair (property_identifier) (null)))))"); + AssertThat(ranges, Equals(vector({}))); + + // Insert leading whitespace again + ranges = get_invalidated_ranges_for_edit([&]() { + return input->replace(0, 0, "\n"); + }); + assert_node_string_equals( + ts_document_root_node(document), + "(program (expression_statement (object (pair (property_identifier) (null)))))"); + AssertThat(ranges, Equals(vector({}))); + }); + it("reports changes when tokens have been appended", [&]() { // Add a second key-value pair auto ranges = get_invalidated_ranges_for_edit([&]() {