From f8d31ee04c1069eefd664c317ce59f5bea03f734 Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Tue, 31 Mar 2026 10:46:27 -0400 Subject: [PATCH] Prevent adding `end` token on endless methods --- lib/ruby_lsp/requests/on_type_formatting.rb | 4 + test/requests/on_type_formatting_test.rb | 82 +++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/lib/ruby_lsp/requests/on_type_formatting.rb b/lib/ruby_lsp/requests/on_type_formatting.rb index 257341deec..da4904e192 100644 --- a/lib/ruby_lsp/requests/on_type_formatting.rb +++ b/lib/ruby_lsp/requests/on_type_formatting.rb @@ -120,6 +120,10 @@ def handle_statement_end return unless END_REGEXES.any? { |regex| regex.match?(@previous_line) } + # Endless method definitions (e.g., `def foo = 42`) are complete statements + # and should not have `end` added + return if @previous_line.match?(/\bdef\s+[\w.]+[!?=]?(\([^)]*\))?\s*=[^=~>]/) + indents = " " * @indentation current_line = @lines[@position[:line]] next_line = @lines[@position[:line] + 1] diff --git a/test/requests/on_type_formatting_test.rb b/test/requests/on_type_formatting_test.rb index 44adb0ecaf..69a75a9fe3 100644 --- a/test/requests/on_type_formatting_test.rb +++ b/test/requests/on_type_formatting_test.rb @@ -1122,4 +1122,86 @@ def test_allows_end_completion_when_parenthesis_are_present ] assert_equal(expected_edits.to_json, edits.to_json) end + + def test_does_not_add_end_for_endless_method + document = RubyLsp::RubyDocument.new( + source: +"", + version: 1, + uri: URI("file:///fake.rb"), + global_state: @global_state, + ) + + document.push_edits( + [{ + range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } }, + text: "def foo = 42", + }], + version: 2, + ) + document.parse! + + edits = RubyLsp::Requests::OnTypeFormatting.new( + document, + { line: 1, character: 0 }, + "\n", + "Visual Studio Code", + ).perform + + assert_empty(edits) + end + + def test_does_not_add_end_for_multiline_endless_method + document = RubyLsp::RubyDocument.new( + source: +"", + version: 1, + uri: URI("file:///fake.rb"), + global_state: @global_state, + ) + + document.push_edits( + [{ + range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } }, + text: "def hello = puts(", + }], + version: 2, + ) + document.parse! + + edits = RubyLsp::Requests::OnTypeFormatting.new( + document, + { line: 1, character: 0 }, + "\n", + "Visual Studio Code", + ).perform + + assert_empty(edits) + end + + def test_does_not_add_end_for_endless_method_with_equals_and_parameters + document = RubyLsp::RubyDocument.new( + source: +"", + version: 1, + uri: URI("file:///fake.rb"), + global_state: @global_state, + ) + + # This is actually invalid Ruby. It crashes with a syntax error. But we shouldn't add the `end` token anyway + document.push_edits( + [{ + range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } }, + text: "def foo=(bar) = 42", + }], + version: 2, + ) + document.parse! + + edits = RubyLsp::Requests::OnTypeFormatting.new( + document, + { line: 1, character: 0 }, + "\n", + "Visual Studio Code", + ).perform + + assert_empty(edits) + end end