Class: RubyLsp::Rails::CodeLens

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Includes:
Requests::Support::Common, ActiveSupportTestCaseHelper
Defined in:
lib/ruby_lsp/ruby_lsp_rails/code_lens.rb

Overview

![CodeLens demo](../../code_lens.gif)

This feature adds several CodeLens features for Rails applications using Active Support test cases:

  • Run tests in the VS Terminal

  • Run tests in the VS Code Test Explorer

  • Debug tests

The [code lens](microsoft.github.io/language-server-protocol/specification#textDocument_codeLens) request informs the editor of runnable commands such as tests. It’s available for tests which inherit from ‘ActiveSupport::TestCase` or one of its descendants, such as `ActionDispatch::IntegrationTest`.

# Example:

For the following code, Code Lenses will be added above the class definition above each test method.

“‘ruby Run class HelloTest < ActiveSupport::TestCase # <- Will show code lenses above for running or debugging the whole test

test "outputs hello" do # <- Will show code lenses above for running or debugging this test
  # ...
end

test "outputs goodbye" do # <- Will show code lenses above for running or debugging this test
  # ...
end

end ““

The code lenses will be displayed above the class and above each test method.

Note: When using the Test Explorer view, if your code contains a statement to pause execution (e.g. ‘debugger`) it will cause the test runner to hang.

Instance Method Summary collapse

Methods included from ActiveSupportTestCaseHelper

#extract_test_case_name

Constructor Details

#initialize(response_builder, uri, dispatcher) ⇒ CodeLens

Returns a new instance of CodeLens.



53
54
55
56
57
58
59
60
# File 'lib/ruby_lsp/ruby_lsp_rails/code_lens.rb', line 53

def initialize(response_builder, uri, dispatcher)
  @response_builder = response_builder
  @path = T.let(uri.to_standardized_path, T.nilable(String))
  @group_id = T.let(1, Integer)
  @group_id_stack = T.let([], T::Array[Integer])

  dispatcher.register(self, :on_call_node_enter, :on_class_node_enter, :on_def_node_enter, :on_class_node_leave)
end

Instance Method Details

#on_call_node_enter(node) ⇒ Object



63
64
65
66
67
68
69
70
71
# File 'lib/ruby_lsp/ruby_lsp_rails/code_lens.rb', line 63

def on_call_node_enter(node)
  content = extract_test_case_name(node)

  return unless content

  line_number = node.location.start_line
  command = "#{test_command} #{@path}:#{line_number}"
  add_test_code_lens(node, name: content, command: command, kind: :example)
end

#on_class_node_enter(node) ⇒ Object



85
86
87
88
89
90
91
92
93
# File 'lib/ruby_lsp/ruby_lsp_rails/code_lens.rb', line 85

def on_class_node_enter(node)
  class_name = node.constant_path.slice
  if class_name.end_with?("Test")
    command = "#{test_command} #{@path}"
    add_test_code_lens(node, name: class_name, command: command, kind: :group)
    @group_id_stack.push(@group_id)
    @group_id += 1
  end
end

#on_class_node_leave(node) ⇒ Object



96
97
98
99
100
101
# File 'lib/ruby_lsp/ruby_lsp_rails/code_lens.rb', line 96

def on_class_node_leave(node)
  class_name = node.constant_path.slice
  if class_name.end_with?("Test")
    @group_id_stack.pop
  end
end

#on_def_node_enter(node) ⇒ Object



75
76
77
78
79
80
81
82
# File 'lib/ruby_lsp/ruby_lsp_rails/code_lens.rb', line 75

def on_def_node_enter(node)
  method_name = node.name.to_s
  if method_name.start_with?("test_")
    line_number = node.location.start_line
    command = "#{test_command} #{@path}:#{line_number}"
    add_test_code_lens(node, name: method_name, command: command, kind: :example)
  end
end