Class: RubyLsp::Rails::Addon

Inherits:
Addon
  • Object
show all
Defined in:
lib/ruby_lsp/ruby_lsp_rails/addon.rb

Constant Summary collapse

RUN_MIGRATIONS_TITLE =
"Run Migrations"

Instance Method Summary collapse

Constructor Details

#initializeAddon

: -> void



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 26

def initialize
  super

  # We first initialize the client as a NullClient, so that we can start the server in a background thread. Until
  # the real client is initialized, features that depend on it will not be blocked by using the NullClient
  @rails_runner_client = NullClient.new #: RunnerClient
  @global_state = nil #: GlobalState?
  @outgoing_queue = nil #: Thread::Queue?
  @settings = {
    enablePendingMigrationsPrompt: true,
  } #: Hash[Symbol, untyped],

  @addon_mutex = Mutex.new #: Mutex
  @client_mutex = Mutex.new #: Mutex
  @client_mutex.lock

  @boot_thread = Thread.new do
    @addon_mutex.synchronize do
      # We need to ensure the Rails client is fully loaded before we activate the server addons
      @client_mutex.synchronize do
        @rails_runner_client = RunnerClient.create_client(
          @outgoing_queue, #: as !nil
          @global_state, #: as !nil
        )
      end
      offer_to_run_pending_migrations
    end
  end #: Thread
end

Instance Method Details

#activate(global_state, outgoing_queue) ⇒ Object

: (GlobalState global_state, Thread::Queue outgoing_queue) -> void



63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 63

def activate(global_state, outgoing_queue)
  @global_state = global_state
  @outgoing_queue = outgoing_queue
  @outgoing_queue << Notification.window_log_message("Activating Ruby LSP Rails add-on v#{VERSION}")

  addon_settings = @global_state.settings_for_addon(name)
  @settings.merge!(addon_settings) if addon_settings

  register_additional_file_watchers(global_state: global_state, outgoing_queue: outgoing_queue)

  # Start booting the real client in a background thread. Until this completes, the client will be a NullClient
  @client_mutex.unlock
end

#create_code_lens_listener(response_builder, uri, dispatcher) ⇒ Object

Creates a new CodeLens listener. This method is invoked on every CodeLens request : (ResponseBuilders::CollectionResponseBuilder response_builder, URI::Generic uri, Prism::Dispatcher dispatcher) -> void



107
108
109
110
111
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 107

def create_code_lens_listener(response_builder, uri, dispatcher)
  return unless @global_state

  CodeLens.new(@rails_runner_client, @global_state, response_builder, uri, dispatcher)
end

#create_completion_listener(response_builder, node_context, dispatcher, uri) ⇒ Object

: (ResponseBuilders::CollectionResponseBuilder response_builder, NodeContext node_context, Prism::Dispatcher dispatcher, URI::Generic uri) -> void



137
138
139
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 137

def create_completion_listener(response_builder, node_context, dispatcher, uri)
  Completion.new(@rails_runner_client, response_builder, node_context, dispatcher, uri)
end

#create_definition_listener(response_builder, uri, node_context, dispatcher) ⇒ Object

: (ResponseBuilders::CollectionResponseBuilder[(Interface::Location | Interface::LocationLink)] response_builder, URI::Generic uri, NodeContext node_context, Prism::Dispatcher dispatcher) -> void



129
130
131
132
133
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 129

def create_definition_listener(response_builder, uri, node_context, dispatcher)
  return unless @global_state

  Definition.new(@rails_runner_client, response_builder, node_context, @global_state.graph, dispatcher)
end

#create_discover_tests_listener(response_builder, dispatcher, uri) ⇒ Object

: (ResponseBuilders::TestCollection response_builder, Prism::Dispatcher dispatcher, URI::Generic uri) -> void



92
93
94
95
96
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 92

def create_discover_tests_listener(response_builder, dispatcher, uri)
  return unless @global_state

  RailsTestStyle.new(response_builder, @global_state, dispatcher, uri)
end

#create_document_symbol_listener(response_builder, dispatcher) ⇒ Object

: (ResponseBuilders::DocumentSymbol response_builder, Prism::Dispatcher dispatcher) -> Object



123
124
125
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 123

def create_document_symbol_listener(response_builder, dispatcher)
  DocumentSymbol.new(response_builder, dispatcher)
end

#create_hover_listener(response_builder, node_context, dispatcher) ⇒ Object

: (ResponseBuilders::Hover response_builder, NodeContext node_context, Prism::Dispatcher dispatcher) -> void



115
116
117
118
119
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 115

def create_hover_listener(response_builder, node_context, dispatcher)
  return unless @global_state

  Hover.new(@rails_runner_client, response_builder, node_context, @global_state, dispatcher)
end

#deactivateObject

: -> void



79
80
81
82
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 79

def deactivate
  @boot_thread.join
  @rails_runner_client.shutdown
end

#handle_window_show_message_response(title) ⇒ Object

: (String title) -> void



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 167

def handle_window_show_message_response(title)
  if title == RUN_MIGRATIONS_TITLE

    begin_progress("run-migrations", "Running Migrations")
    response = @rails_runner_client.run_migrations

    if response && @outgoing_queue
      if response[:status] == 0
        # Both log the message and show it as part of progress because sometimes running migrations is so fast you
        # can't see the progress notification
        @outgoing_queue << Notification.window_log_message(response[:message])
        report_progress("run-migrations", message: response[:message])
      else
        @outgoing_queue << Notification.window_show_message(
          "Migrations failed to run\n\n#{response[:message]}",
          type: Constant::MessageType::ERROR,
        )
      end
    end

    end_progress("run-migrations")
  end
end

#nameObject

: -> String



161
162
163
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 161

def name
  "Ruby LSP Rails"
end

#rails_runner_clientObject

: -> RunnerClient



57
58
59
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 57

def rails_runner_client
  @addon_mutex.synchronize { @rails_runner_client }
end

#resolve_test_commands(items) ⇒ Object

: (Array[Hash[Symbol, untyped]]) -> Array



100
101
102
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 100

def resolve_test_commands(items)
  RailsTestStyle.resolve_test_commands(items)
end

#versionObject

: -> String



86
87
88
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 86

def version
  VERSION
end

#workspace_did_change_watched_files(changes) ⇒ Object

: (Array[String, type: Integer] changes) -> void



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/ruby_lsp/ruby_lsp_rails/addon.rb', line 142

def workspace_did_change_watched_files(changes)
  if changes.any? { |c| c[:uri].end_with?("db/schema.rb") || c[:uri].end_with?("structure.sql") }
    @rails_runner_client.trigger_reload
  end

  if changes.any? do |c|
       %r{db/migrate/.*\.rb}.match?(c[:uri]) && c[:type] != Constant::FileChangeType::CHANGED
     end

    offer_to_run_pending_migrations
  end

  if changes.any? { |c| %r{config/locales/.*\.yml}.match?(c[:uri]) }
    @rails_runner_client.trigger_i18n_reload
  end
end