class RubyLsp::Listeners::SpecStyle
def add_to_parent_test_group(description, node)
def add_to_parent_test_group(description, node) parent_test_group = find_parent_test_group return unless parent_test_group test_item = Requests::Support::TestItem.new( description, description, @uri, range_from_node(node), framework: :minitest, ) parent_test_group.add(test_item) @response_builder.add_code_lens(test_item) end
def extract_description(node)
def extract_description(node) first_argument = node.arguments&.arguments&.first return unless first_argument case first_argument when Prism::StringNode first_argument.content when Prism::ConstantReadNode, Prism::ConstantPathNode constant_name(first_argument) else first_argument.slice end end
def find_parent_test_group
def find_parent_test_group root_group_name, nested_describe_groups = if @nesting.empty? [@describe_block_nesting.first, @describe_block_nesting[1..]] else [RubyIndexer::Index.actual_nesting(@nesting, nil).join("::"), @describe_block_nesting] end return unless root_group_name test_group = @response_builder[root_group_name] #: Requests::Support::TestItem? return unless test_group return test_group unless nested_describe_groups nested_describe_groups.each do |description| test_group = test_group[description] end test_group end
def handle_describe(node)
def handle_describe(node) return if node.block.nil? description = extract_description(node) return unless description return unless in_spec_context? if @nesting.empty? && @describe_block_nesting.empty? test_item = Requests::Support::TestItem.new( description, description, @uri, range_from_node(node), framework: :minitest, ) @response_builder.add(test_item) @response_builder.add_code_lens(test_item) else add_to_parent_test_group(description, node) end @describe_block_nesting << description end
def handle_example(node)
def handle_example(node) return unless in_spec_context? return if @describe_block_nesting.empty? && @nesting.empty? description = extract_description(node) return unless description add_to_parent_test_group(description, node) end
def in_spec_context?
def in_spec_context? return true if @nesting.empty? @spec_class_stack.last #: as !nil end
def initialize(response_builder, global_state, dispatcher, uri)
def initialize(response_builder, global_state, dispatcher, uri) super @describe_block_nesting = [] #: Array[String] @spec_class_stack = [] #: Array[bool] dispatcher.register( self, # Common handlers registered in parent class :on_class_node_enter, :on_call_node_enter, # e.g. `describe` or `it` :on_call_node_leave, ) end
def on_call_node_enter(node)
def on_call_node_enter(node) case node.name when :describe handle_describe(node) when :it, :specify handle_example(node) end end
def on_call_node_leave(node)
def on_call_node_leave(node) return unless node.name == :describe && !node.receiver @describe_block_nesting.pop end
def on_class_node_enter(node)
def on_class_node_enter(node) with_test_ancestor_tracking(node) do |_, ancestors| is_spec = ancestors.include?("Minitest::Spec") @spec_class_stack.push(is_spec) end end
def on_class_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
: (Prism::ClassNode) -> void
def on_class_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod super @spec_class_stack.pop end