diff --git a/lib/ruby_lsp/global_state.rb b/lib/ruby_lsp/global_state.rb index 0836ca880..17f674c39 100644 --- a/lib/ruby_lsp/global_state.rb +++ b/lib/ruby_lsp/global_state.rb @@ -204,7 +204,7 @@ def apply_options(options) Encoding::UTF_16LE else @graph.encoding = "utf32" - Encoding::UTF_32 + Encoding::UTF_32LE end @index.configuration.encoding = @encoding diff --git a/test/global_state_test.rb b/test/global_state_test.rb index 35f96e754..91a114a09 100644 --- a/test/global_state_test.rb +++ b/test/global_state_test.rb @@ -219,6 +219,22 @@ def test_delegates_supports_watching_files_to_client_capabilities global_state.supports_watching_files end + def test_utf32_negotiation_yields_encoding_compatible_with_prism_code_units_cache + state = GlobalState.new + state.apply_options(capabilities: { general: { positionEncodings: ["utf-32"] } }) + + source = "class Foo; end\n\"🙂\"; Foo\n" + result = Prism.parse(source) + cache = result.code_units_cache(state.encoding) + foo_ref = result.value.statements.body.last #: as !nil + + # `Foo` on line 1 starts at byte 23 (`class Foo; end\n` = 15 bytes + `"🙂"; ` = 8 bytes). + # In UTF-32 code units that same position is codepoint 20 (15 + 5). If `state.encoding` + # returns the dummy `Encoding::UTF_32`, the cache cannot translate past `🙂` and this + # assertion fails with a non-20 value. + assert_equal(20, foo_ref.location.cached_start_code_units_offset(cache)) + end + def test_feature_flags_are_processed_by_apply_options state = GlobalState.new