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|class|module|until|def|case)\b.*/,
    /.*\s\bdo\b/,
  ],
  T::Array[Regexp],
)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document, position, trigger_character) ⇒ OnTypeFormatting

Returns a new instance of OnTypeFormatting.



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/ruby_lsp/requests/on_type_formatting.rb', line 42

def initialize(document, position, trigger_character)
  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
end

Class Method Details

.providerObject



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

def provider
  Interface::DocumentOnTypeFormattingOptions.new(
    first_trigger_character: "{",
    more_trigger_character: ["\n", "|", "d"],
  )
end

Instance Method Details

#performObject



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/ruby_lsp/requests/on_type_formatting.rb', line 56

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