88require_relative "document_symbol"
99require_relative "definition"
1010require_relative "indexing_enhancement"
11+ require_relative "test_discovery"
12+ require_relative "spec_style_patch"
1113
1214module RubyLsp
1315 module RSpec
1416 class Addon < ::RubyLsp ::Addon
1517 extend T ::Sig
1618
19+ FORMATTER_PATH = T . let ( File . expand_path ( "rspec_formatter.rb" , __dir__ ) , String )
20+ FORMATTER_NAME = T . let ( "RubyLsp::RSpec::RSpecFormatter" , String )
21+
1722 sig { returns ( T ::Boolean ) }
1823 attr_reader :debug
1924
@@ -30,12 +35,18 @@ def activate(global_state, message_queue)
3035
3136 settings = global_state . settings_for_addon ( name )
3237 @rspec_command = rspec_command ( settings )
38+ @workspace_path = T . let ( global_state . workspace_path , T . nilable ( String ) )
3339 @debug = settings &.dig ( :debug ) || false
3440 end
3541
3642 sig { override . void }
3743 def deactivate ; end
3844
45+ sig { override . returns ( String ) }
46+ def name
47+ "ruby-lsp-rspec"
48+ end
49+
3950 sig { override . returns ( String ) }
4051 def version
4152 VERSION
@@ -55,6 +66,68 @@ def create_code_lens_listener(response_builder, uri, dispatcher)
5566 CodeLens . new ( response_builder , uri , dispatcher , T . must ( @rspec_command ) , debug : debug )
5667 end
5768
69+ # Creates a new Discover Tests listener. This method is invoked on every DiscoverTests request
70+ sig do
71+ override . params (
72+ response_builder : ResponseBuilders ::TestCollection ,
73+ dispatcher : Prism ::Dispatcher ,
74+ uri : URI ::Generic ,
75+ ) . void
76+ end
77+ def create_discover_tests_listener ( response_builder , dispatcher , uri )
78+ return unless uri . to_standardized_path &.end_with? ( "_spec.rb" )
79+
80+ TestDiscovery . new ( response_builder , dispatcher , uri , T . must ( @workspace_path ) )
81+ end
82+
83+ # Resolves the minimal set of commands required to execute the requested tests
84+ sig do
85+ override . params (
86+ items : T ::Array [ T ::Hash [ Symbol , T . untyped ] ] ,
87+ ) . returns ( T ::Array [ String ] )
88+ end
89+ def resolve_test_commands ( items )
90+ commands = [ ]
91+ queue = items . dup
92+
93+ full_files = [ ]
94+
95+ until queue . empty?
96+ item = T . must ( queue . shift )
97+ tags = Set . new ( item [ :tags ] )
98+ next unless tags . include? ( "framework:rspec" )
99+
100+ children = item [ :children ]
101+ uri = URI ( item [ :uri ] )
102+ path = uri . full_path
103+ next unless path
104+
105+ if tags . include? ( "test_dir" )
106+ if children . empty?
107+ full_files . concat ( Dir . glob (
108+ "#{ path } /**/*_spec.rb" ,
109+ File ::Constants ::FNM_EXTGLOB | File ::Constants ::FNM_PATHNAME ,
110+ ) )
111+ end
112+ elsif tags . include? ( "test_file" )
113+ full_files << path if children . empty?
114+ elsif tags . include? ( "test_group" )
115+ start_line = item . dig ( :range , :start , :line )
116+ commands << "#{ @rspec_command } -r #{ FORMATTER_PATH } -f #{ FORMATTER_NAME } #{ path } :#{ start_line + 1 } "
117+ else
118+ full_files << "#{ path } :#{ item . dig ( :range , :start , :line ) + 1 } "
119+ end
120+
121+ queue . concat ( children )
122+ end
123+
124+ unless full_files . empty?
125+ commands << "#{ @rspec_command } -r #{ FORMATTER_PATH } -f #{ FORMATTER_NAME } #{ full_files . join ( " " ) } "
126+ end
127+
128+ commands
129+ end
130+
58131 sig do
59132 override . params (
60133 response_builder : ResponseBuilders ::DocumentSymbol ,
@@ -67,10 +140,7 @@ def create_document_symbol_listener(response_builder, dispatcher)
67140
68141 sig do
69142 override . params (
70- response_builder : ResponseBuilders ::CollectionResponseBuilder [ T . any (
71- Interface ::Location ,
72- Interface ::LocationLink ,
73- ) ] ,
143+ response_builder : ResponseBuilders ::CollectionResponseBuilder [ T . any ( Interface ::Location , Interface ::LocationLink ) ] ,
74144 uri : URI ::Generic ,
75145 node_context : NodeContext ,
76146 dispatcher : Prism ::Dispatcher ,
@@ -82,10 +152,7 @@ def create_definition_listener(response_builder, uri, node_context, dispatcher)
82152 Definition . new ( response_builder , uri , node_context , T . must ( @index ) , dispatcher )
83153 end
84154
85- sig { override . returns ( String ) }
86- def name
87- "Ruby LSP RSpec"
88- end
155+ private
89156
90157 sig { params ( settings : T . nilable ( T ::Hash [ Symbol , T . untyped ] ) ) . returns ( String ) }
91158 def rspec_command ( settings )
0 commit comments