Class: RubyLsp::Requests::OnTypeFormatting

Inherits:
Request
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/ruby_lsp/requests/on_type_formatting.rb

Overview

![On type formatting demo](../../on_type_formatting.gif)

The [on type formatting](microsoft.github.io/language-server-protocol/specification#textDocument_onTypeFormatting) request formats code as the user is typing. For example, automatically adding ‘end` to class definitions.

# Example

“‘ruby class Foo # <– upon adding a line break, on type formatting is triggered

# <-- cursor ends up here

end # <– end is automatically added “‘

Constant Summary collapse

END_REGEXES =
T.let(
  [
    /\b(if|unless|for|while|until)\b($|\s|\()/,
    /\b(class|module|def|case)\b($|\s)/,
    /.*\s\bdo\b($|\s)/,
  ],
  T::Array[Regexp],
)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document, position, trigger_character, client_name) ⇒ OnTypeFormatting

Returns a new instance of OnTypeFormatting.



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/ruby_lsp/requests/on_type_formatting.rb', line 51

def initialize(document, position, trigger_character, client_name)
  super()
  @document = document
  @lines = T.let(@document.source.lines, T::Array[String])
  line = @lines[[position[:line] - 1, 0].max]

  @indentation = T.let(line ? find_indentation(line) : 0, Integer)
  @previous_line = T.let(line ? line.strip.chomp : "", String)
  @position = position
  @edits = T.let([], T::Array[Interface::TextEdit])
  @trigger_character = trigger_character
  @client_name = client_name
end

Class Method Details

.providerObject



25
26
27
28
29
30
31
# File 'lib/ruby_lsp/requests/on_type_formatting.rb', line 25

def provider
  Interface::DocumentOnTypeFormattingRegistrationOptions.new(
    document_selector: [Interface::DocumentFilter.new(language: "ruby")],
    first_trigger_character: "{",
    more_trigger_character: ["\n", "|", "d"],
  )
end

Instance Method Details

#performObject



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/ruby_lsp/requests/on_type_formatting.rb', line 66

def perform
  case @trigger_character
  when "{"
    handle_curly_brace if @document.syntax_error?
  when "|"
    handle_pipe if @document.syntax_error?
  when "\n"
    if (comment_match = @previous_line.match(/^#(\s*)/))
      handle_comment_line(T.must(comment_match[1]))
    elsif @document.syntax_error?
      match = /(?<=<<(-|~))(?<quote>['"`]?)(?<delimiter>\w+)\k<quote>/.match(@previous_line)
      heredoc_delimiter = match && match.named_captures["delimiter"]

      if heredoc_delimiter
        handle_heredoc_end(heredoc_delimiter)
      else
        handle_statement_end
      end
    end
  when "d"
    auto_indent_after_end_keyword
  end

  @edits
end