diff --git a/lib/ruby_lsp/document.rb b/lib/ruby_lsp/document.rb index 4bd9e9120..57fca07b7 100644 --- a/lib/ruby_lsp/document.rb +++ b/lib/ruby_lsp/document.rb @@ -28,7 +28,7 @@ def initialize(source:, version:, uri:, encoding: Constant::PositionEncodingKind @source = T.let(source, String) @version = T.let(version, Integer) @uri = T.let(uri, URI::Generic) - @unparsed_edits = T.let([], T::Array[EditShape]) + @needs_parsing = T.let(false, T::Boolean) @parse_result = T.let(YARP.parse(@source), YARP::ParseResult) end @@ -87,15 +87,15 @@ def push_edits(edits, version:) end @version = version - @unparsed_edits.concat(edits) + @needs_parsing = true @cache.clear end sig { void } def parse - return if @unparsed_edits.empty? + return unless @needs_parsing - @unparsed_edits.clear + @needs_parsing = false @parse_result = YARP.parse(@source) end diff --git a/test/document_test.rb b/test/document_test.rb index cf7e319fc..3724e1ebd 100644 --- a/test/document_test.rb +++ b/test/document_test.rb @@ -502,13 +502,26 @@ def baz def test_reparsing_without_new_edits_does_nothing document = RubyLsp::Document.new(source: +"", version: 1, uri: URI("file:///foo/bar.rb")) document.push_edits( - [{ range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } }, text: "def foo" }], + [{ range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } }, text: "def foo; end" }], version: 2, ) + # When there's a new edit, we parse it the first `parse` invocation + YARP.expects(:parse).with(document.source).once + document.parse + + # If there are no new edits, we don't do anything + YARP.expects(:parse).never + document.parse + + document.push_edits( + [{ range: { start: { line: 0, character: 12 }, end: { line: 0, character: 12 } }, text: "\ndef bar; end" }], + version: 3, + ) + + # If there's another edit, we parse it once again + YARP.expects(:parse).with(document.source).once document.parse - assert_predicate(document, :syntax_error?) - assert_empty(document.instance_variable_get(:@unparsed_edits)) end def test_cache_set_and_get