solargraph-rspec 0.1.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46e92fa0735bc1e0b1129ce3c06208969dd8917a28e70286876d7f6307928e8c
4
- data.tar.gz: 718485f0ea53780cb3ee6d076cb5be112d160d1c39866c91334142d1abff515a
3
+ metadata.gz: 25d0ca1f34e0cf80057b86a412ec10cbacba388a96bd5b5e7b93f64457616e5a
4
+ data.tar.gz: d1b4b825f9df08a3333bab32d2af05a9cc6a48cd7903f5b4504baba1e775a960
5
5
  SHA512:
6
- metadata.gz: '06580663bc8c5424219a171e4f61121d98d04dfe9048bfaa3595c7717bdd2a88b6dcd5055218cbf2fe3c50f7ade5a148811a7c23b780c86d9f0bae8ea554a236'
7
- data.tar.gz: 28ea8fe4be4f3402ca3079a747764013d6154adac0b114c2f9f23afe81599b403f0bb024856c3744ce7e8b64f80898eba210962cec68253e0edf25c90f3ce1d6
6
+ metadata.gz: 1d7efb9da09a862654e5bb4fbd70bb983230cae9303e98ebc487cb0f00afe752ba8c936513dc23aac153e99f49d607b93111aada2f235fb47fdbeefcb81a0acb
7
+ data.tar.gz: aa9563e0d56a8ab37b45a739f6394e47e7dd597bc59bfb205a043ed41d9b5c47bc08b7a8184225ed75f2840bd57aeedd96ed05f325d32700c54e81aafb3e39d3
data/CHANGELOG.md CHANGED
@@ -7,7 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- -
10
+
11
+ ## [0.2.1] - 2024-06-09
12
+
13
+ ### Added
14
+
15
+ - Documentation for `RSpec::ExampleGroups` DSL methods like `it`, `fit`, `example` etc.
16
+
17
+ ### Fixed
18
+
19
+ - Fix nameless `subject` method completion inside nested `context` blocks
20
+ - (Hack-ish) Fix `described_class` type collision when `RSpec.describe SomeClassWithoutNamespace`
21
+
22
+ ## [0.2.0] - 2024-05-20
23
+
24
+ ### Added
25
+
26
+ - `let` and `subject` type inference 🚀 (Resolves: [Issue #1](https://github.com/lekemula/solargraph-rspec/issues/1))
27
+
28
+ ### Changed
29
+
30
+ - Migrate from `parser` gem to using ruby's built-in RubyVM::AbstractSyntaxTree ([see why](https://github.com/castwide/solargraph/issues/522#issuecomment-993016664))
31
+
32
+ ### Fixed
33
+
34
+ - Fix subject without name block completion: `subject { ... }`
35
+ - Fix subject return class overlap with `Rspec::ExampleGroups::` when class has no namespace
11
36
 
12
37
  ## [0.1.1] - 2024-05-13
13
38
 
data/README.md CHANGED
@@ -7,15 +7,18 @@
7
7
 
8
8
  RSpec is a testing framework of choice for many Ruby developers. But at the same time is highly dynamic and heavily relying on metaprogramming making it hard to provide accurate code completion and type inference.
9
9
 
10
- This gem aims to provide a better support for RSpec in Solargraph and it supports the following features:
10
+ This gem aims to provide better support for RSpec in Solargraph and it supports the following features:
11
11
  - `describe` and `it` methods completion
12
12
  - memoized `let` and `let!` methods completion
13
13
  - implicit and explicit `subject` methods
14
14
  - `described_class` with appropriate type inference
15
15
  - `RSpec::Matchers` methods completion
16
+ - type inference 🚀
16
17
  - and more to come...
17
18
 
18
- ![solargraph-rspec_smaller](https://github.com/lekemula/solargraph-rspec/assets/9197495/66f86e5b-258e-4d8c-8a64-0685d15ece00)
19
+ ![solargraph-rspec-with-types](https://github.com/lekemula/solargraph-rspec/assets/9197495/077e74f8-a800-4e90-8922-fa5351adcda3)
20
+ ![solargraph-rspec-with-types-vs-code](https://github.com/lekemula/solargraph-rspec/assets/9197495/6a942460-256d-46ca-82de-9869a65309ec)
21
+
19
22
 
20
23
  ## Installation
21
24
 
data/codecov.yml ADDED
@@ -0,0 +1,13 @@
1
+ # https://docs.codecov.com/docs/common-recipe-list
2
+ coverage:
3
+ status:
4
+ project: #add everything under here, more options at https://docs.codecov.com/docs/commit-status
5
+ default:
6
+ # basic
7
+ target: auto #default
8
+ threshold: 1%
9
+ base: auto
10
+ informational: true
11
+ patch:
12
+ default:
13
+ informational: true
@@ -8,9 +8,8 @@ require_relative 'correctors/described_class_corrector'
8
8
  require_relative 'correctors/let_methods_corrector'
9
9
  require_relative 'correctors/subject_method_corrector'
10
10
  require_relative 'correctors/context_block_methods_corrector'
11
- require_relative 'correctors/implicit_subject_method_corrector'
12
11
  require_relative 'correctors/dsl_methods_corrector'
13
- require_relative 'util'
12
+ require_relative 'pin_factory'
14
13
 
15
14
  module Solargraph
16
15
  module Rspec
@@ -50,6 +49,17 @@ module Solargraph
50
49
  include_context
51
50
  ].freeze
52
51
 
52
+ # @type [Array<Class<Correctors::Base>>]
53
+ CORRECTOR_CLASSES = [
54
+ Correctors::ContextBlockMethodsCorrector,
55
+ Correctors::ContextBlockNamespaceCorrector,
56
+ Correctors::DescribedClassCorrector,
57
+ Correctors::DslMethodsCorrector,
58
+ Correctors::ExampleAndHookBlocksBindingCorrector,
59
+ Correctors::LetMethodsCorrector,
60
+ Correctors::SubjectMethodCorrector
61
+ ].freeze
62
+
53
63
  # Provides completion for RSpec DSL and helper methods.
54
64
  # - `describe` and `context` blocks
55
65
  # - `let` and `let!` methods
@@ -105,77 +115,17 @@ module Solargraph
105
115
 
106
116
  rspec_walker = SpecWalker.new(source_map: source_map, config: config)
107
117
 
108
- Correctors::ContextBlockNamespaceCorrector.new(
109
- namespace_pins: namespace_pins,
110
- rspec_walker: rspec_walker
111
- ).correct(source_map) do |pins_to_add|
112
- pins += pins_to_add
113
- end
114
-
115
- Correctors::ExampleAndHookBlocksBindingCorrector.new(
116
- namespace_pins: namespace_pins,
117
- rspec_walker: rspec_walker
118
- ).correct(source_map) do |pins_to_add|
119
- pins += pins_to_add
120
- end
121
-
122
- # @type [Pin::Method, nil]
123
- described_class_pin = nil
124
- Correctors::DescribedClassCorrector.new(namespace_pins: namespace_pins, rspec_walker: rspec_walker).correct(
125
- source_map
126
- ) do |pins_to_add|
127
- described_class_pin = pins_to_add.first
128
- pins += pins_to_add
129
- end
130
-
131
- Correctors::LetMethodsCorrector.new(namespace_pins: namespace_pins, rspec_walker: rspec_walker).correct(
132
- source_map
133
- ) do |pins_to_add|
134
- pins += pins_to_add
135
- end
136
-
137
- # @type [Pin::Method, nil]
138
- subject_pin = nil
139
- Correctors::SubjectMethodCorrector.new(namespace_pins: namespace_pins, rspec_walker: rspec_walker).correct(
140
- source_map
141
- ) do |pins_to_add|
142
- subject_pin = pins_to_add.first
143
- pins += pins_to_add
144
- end
145
-
146
- Correctors::ContextBlockMethodsCorrector.new(
147
- namespace_pins: namespace_pins,
148
- rspec_walker: rspec_walker
149
- ).correct(source_map) do |pins_to_add|
150
- pins += pins_to_add
151
- end
152
-
153
- Correctors::DslMethodsCorrector.new(
154
- namespace_pins: namespace_pins,
155
- rspec_walker: rspec_walker,
156
- config: config
157
- ).correct(
158
- source_map
159
- ) do |pins_to_add|
160
- pins += pins_to_add
118
+ CORRECTOR_CLASSES.each do |corrector_class|
119
+ corrector_class.new(
120
+ namespace_pins: namespace_pins,
121
+ rspec_walker: rspec_walker,
122
+ added_pins: pins
123
+ ).correct(source_map)
161
124
  end
162
125
 
163
126
  rspec_walker.walk!
164
127
  pins += namespace_pins
165
128
 
166
- # Implicit subject
167
- if !subject_pin && described_class_pin
168
- Correctors::ImplicitSubjectMethodCorrector.new(
169
- namespace_pins: namespace_pins,
170
- described_class_pin: described_class_pin
171
- ).correct(
172
- source_map
173
- ) do |pins_to_add|
174
- subject_pin = pins_to_add.first
175
- pins += pins_to_add
176
- end
177
- end
178
-
179
129
  if pins.any?
180
130
  Solargraph.logger.debug(
181
131
  "[RSpec] added #{pins.map(&:inspect)} to #{source_map.filename}"
@@ -199,7 +149,7 @@ module Solargraph
199
149
  # @return [Array<Pin::Base>]
200
150
  def include_helper_pins(helper_modules: HELPER_MODULES)
201
151
  helper_modules.map do |helper_module|
202
- Util.build_module_include(
152
+ PinFactory.build_module_include(
203
153
  root_example_group_namespace_pin,
204
154
  helper_module,
205
155
  root_example_group_namespace_pin.location
@@ -216,7 +166,7 @@ module Solargraph
216
166
  def root_example_group_namespace_pin
217
167
  Solargraph::Pin::Namespace.new(
218
168
  name: ROOT_NAMESPACE,
219
- location: Util.dummy_location('lib/rspec/core/example_group.rb')
169
+ location: PinFactory.dummy_location('lib/rspec/core/example_group.rb')
220
170
  )
221
171
  end
222
172
  end
@@ -9,13 +9,22 @@ module Solargraph
9
9
  # @return [Array<Solargraph::Pin::Namespace>]
10
10
  attr_reader :namespace_pins
11
11
 
12
+ # @return [Solargraph::Rspec::SpecWalker]
13
+ attr_reader :rspec_walker
14
+
15
+ # @return [Array<Solargraph::Pin::Base]
16
+ attr_reader :added_pins
17
+
12
18
  # @param namespace_pins [Array<Solargraph::Pin::Base>]
13
- def initialize(namespace_pins:)
19
+ # @param rspec_walker [Solargraph::Rspec::SpecWalker]
20
+ # @param added_pins [Array<Solargraph::Pin::Base>]
21
+ def initialize(namespace_pins:, rspec_walker:, added_pins: [])
14
22
  @namespace_pins = namespace_pins
23
+ @rspec_walker = rspec_walker
24
+ @added_pins = added_pins
15
25
  end
16
26
 
17
27
  # @param _source_map [Solargraph::SourceMap]
18
- # @yield [Array<Solargraph::Pin::Base>] Pins to be added to the source map
19
28
  # @return [void]
20
29
  def correct(_source_map)
21
30
  raise NotImplementedError
@@ -23,11 +32,25 @@ module Solargraph
23
32
 
24
33
  private
25
34
 
35
+ # @param pin [Solargraph::Pin::Base, nil]
36
+ # @return [void]
37
+ def add_pin(pin)
38
+ return unless pin
39
+
40
+ added_pins.push(pin)
41
+ end
42
+
43
+ # @param pins [Array<Solargraph::Pin::Base>]
44
+ # @return [void]
45
+ def add_pins(*pins)
46
+ added_pins.concat(pins.flatten.compact)
47
+ end
48
+
26
49
  # @return [Solargraph::Pin::Namespace]
27
50
  def root_example_group_namespace_pin
28
51
  Solargraph::Pin::Namespace.new(
29
52
  name: ROOT_NAMESPACE,
30
- location: Util.dummy_location('lib/rspec/core/example_group.rb')
53
+ location: PinFactory.dummy_location('lib/rspec/core/example_group.rb')
31
54
  )
32
55
  end
33
56
 
@@ -6,7 +6,7 @@ module Solargraph
6
6
  module Rspec
7
7
  module Correctors
8
8
  # A corrector that corrects pure ruby method blocks namespace defined inside describe/context blocks.
9
- class ContextBlockMethodsCorrector < WalkerBase
9
+ class ContextBlockMethodsCorrector < Base
10
10
  # @param source_map [Solargraph::SourceMap]
11
11
  def correct(source_map)
12
12
  rspec_walker.after_walk do
@@ -28,8 +28,6 @@ module Solargraph
28
28
  comments: pin.comments
29
29
  )
30
30
  end
31
-
32
- yield [] if block_given?
33
31
  end
34
32
  end
35
33
  end
@@ -1,18 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'walker_base'
3
+ require_relative 'base'
4
4
 
5
5
  module Solargraph
6
6
  module Rspec
7
7
  module Correctors
8
- # A corrector of RSpec parsed pins by Solargraph
9
- class ContextBlockNamespaceCorrector < WalkerBase
8
+ # RSpec generates a namespace class for each context block. This corrector add the pins for those namespaces.
9
+ class ContextBlockNamespaceCorrector < Base
10
10
  # @param source_map [Solargraph::SourceMap]
11
11
  def correct(source_map)
12
- rspec_walker.on_each_context_block do |namespace_name, ast|
13
- original_block_pin = source_map.locate_block_pin(ast.location.begin.line, ast.location.begin.column)
12
+ # @param location_range [Solargraph::Range]
13
+ rspec_walker.on_each_context_block do |namespace_name, location_range|
14
+ original_block_pin = source_map.locate_block_pin(location_range.start.line, location_range.start.column)
14
15
  original_block_pin_index = source_map.pins.index(original_block_pin)
15
- location = Util.build_location(ast, source_map.filename)
16
+ location = PinFactory.build_location(location_range, source_map.filename)
16
17
 
17
18
  # Define a dynamic module for the example group block
18
19
  # Example:
@@ -36,7 +37,7 @@ module Solargraph
36
37
 
37
38
  # Include DSL methods in the example group block
38
39
  # TOOD: This does not work on solagraph! Class methods are not included from parent class.
39
- namespace_extend_pin = Util.build_module_extend(
40
+ namespace_extend_pin = PinFactory.build_module_extend(
40
41
  namespace_pin,
41
42
  root_example_group_namespace_pin.name,
42
43
  location
@@ -44,19 +45,15 @@ module Solargraph
44
45
 
45
46
  # Include parent example groups to share let definitions
46
47
  parent_namespace_name = namespace_name.split('::')[0..-2].join('::')
47
- namespace_include_pin = Util.build_module_include(
48
+ namespace_include_pin = PinFactory.build_module_include(
48
49
  namespace_pin,
49
50
  parent_namespace_name,
50
51
  location
51
52
  )
52
53
 
53
54
  namespace_pins << namespace_pin
54
- if block_given?
55
- yield [
56
- namespace_include_pin,
57
- namespace_extend_pin
58
- ]
59
- end
55
+
56
+ add_pins(namespace_extend_pin, namespace_include_pin)
60
57
  end
61
58
  end
62
59
  end
@@ -1,35 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'walker_base'
3
+ require_relative 'base'
4
4
 
5
5
  module Solargraph
6
6
  module Rspec
7
7
  module Correctors
8
- class DescribedClassCorrector < WalkerBase
8
+ # Defines `described_class` method in the example group block
9
+ class DescribedClassCorrector < Base
9
10
  # @param source_map [Solargraph::SourceMap]
10
11
  # @return [void]
11
12
  def correct(_source_map)
12
- rspec_walker.on_described_class do |ast, described_class_name|
13
- namespace_pin = closest_namespace_pin(namespace_pins, ast.loc.line)
13
+ rspec_walker.on_described_class do |described_class_name, location_range|
14
+ namespace_pin = closest_namespace_pin(namespace_pins, location_range.start.line)
14
15
  next unless namespace_pin
15
16
 
16
- described_class_pin = rspec_described_class_method(namespace_pin, ast, described_class_name)
17
- yield [described_class_pin].compact if block_given?
17
+ described_class_pin = rspec_described_class_method(namespace_pin, location_range, described_class_name)
18
+ add_pin(described_class_pin)
18
19
  end
19
20
  end
20
21
 
21
22
  private
22
23
 
23
24
  # @param namespace [Pin::Namespace]
24
- # @param ast [Parser::AST::Node]
25
+ # @param location_range [Solargraph::Range]
25
26
  # @param described_class_name [String]
26
27
  # @return [Pin::Method, nil]
27
- def rspec_described_class_method(namespace, ast, described_class_name)
28
- Util.build_public_method(
28
+ def rspec_described_class_method(namespace, location_range, described_class_name)
29
+ PinFactory.build_public_method(
29
30
  namespace,
30
31
  'described_class',
31
- types: ["Class<#{described_class_name}>"],
32
- location: Util.build_location(ast, namespace.filename),
32
+ types: ["Class<::#{described_class_name}>"],
33
+ location: PinFactory.build_location(location_range, namespace.filename),
33
34
  scope: :instance
34
35
  )
35
36
  end
@@ -1,44 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'walker_base'
3
+ require_relative 'base'
4
+ require 'yard'
4
5
 
5
6
  module Solargraph
6
7
  module Rspec
7
8
  module Correctors
8
- class DslMethodsCorrector < WalkerBase
9
- # @param namespace_pins [Array<Solargraph::Pin::Base>]
10
- # @param rspec_walker [Solargraph::Rspec::SpecWalker]
11
- # @param config [Solargraph::Rspec::Config]
12
- def initialize(namespace_pins:, rspec_walker:, config:)
13
- super(namespace_pins: namespace_pins, rspec_walker: rspec_walker)
14
- @config = config
9
+ # Includes DSL method helpers in the example group block for completion (ie. it, before, let, subject, etc.)
10
+ class DslMethodsCorrector < Base
11
+ # @return [Array<YARD::CodeObjects::Base>]
12
+ def self.rspec_yardoc_tags
13
+ @rspec_yardoc_tags ||= begin
14
+ spec = Gem::Specification.find_by_name('rspec-core')
15
+ require_paths = spec.require_paths.map { |path| File.join(spec.full_gem_path, path) }
16
+ Solargraph.logger.debug "[RSpec] Loading YARD registry for rspec-core from #{require_paths}"
17
+ YARD::Registry.load(require_paths, true)
18
+ YARD::Registry.all
19
+ end
15
20
  end
16
21
 
17
22
  # @param source_map [Solargraph::SourceMap]
18
23
  # @return [void]
19
24
  def correct(_source_map)
20
25
  rspec_walker.after_walk do
21
- if block_given?
22
- yield namespace_pins.flat_map { |namespace_pin| add_context_dsl_methods(namespace_pin) }
23
- yield namespace_pins.flat_map { |namespace_pin| add_methods_with_example_binding(namespace_pin) }
26
+ namespace_pins.each do |namespace_pin|
27
+ add_pins(context_dsl_methods(namespace_pin))
28
+ add_pins(methods_with_example_binding(namespace_pin))
24
29
  end
25
30
  end
26
31
  end
27
32
 
28
33
  private
29
34
 
30
- # @return [Solargraph::Rspec::Config]
31
- attr_reader :config
32
-
33
35
  # RSpec executes example and hook blocks (eg. it, before, after)in the context of the example group.
34
- # @yieldsef changes the binding of the block to correct class.
36
+ # Tag @yieldsef changes the binding of the block to correct class.
35
37
  # @return [Array<Solargraph::Pin::Method>]
36
- def add_methods_with_example_binding(namespace_pin)
38
+ def methods_with_example_binding(namespace_pin)
37
39
  rspec_context_block_methods.map do |method|
38
- Util.build_public_method(
40
+ # TODO: Add location from YARD registry and documentation for other methods not just example group methods.
41
+ PinFactory.build_public_method(
39
42
  namespace_pin,
40
43
  method.to_s,
41
- comments: ["@yieldself [#{namespace_pin.path}]"], # Fixes the binding of the block to the correct class
44
+ comments: [example_group_documentation(method), "@yieldself [#{namespace_pin.path}]"],
42
45
  scope: :class
43
46
  )
44
47
  end
@@ -48,9 +51,9 @@ module Solargraph
48
51
  # Fix this once Solargraph supports extending class methods.
49
52
  # @param namespace_pin [Solargraph::Pin::Base]
50
53
  # @return [Array<Solargraph::Pin::Base>]
51
- def add_context_dsl_methods(namespace_pin)
54
+ def context_dsl_methods(namespace_pin)
52
55
  Rspec::CONTEXT_METHODS.map do |method|
53
- Util.build_public_method(
56
+ PinFactory.build_public_method(
54
57
  namespace_pin,
55
58
  method.to_s,
56
59
  scope: :class
@@ -58,10 +61,36 @@ module Solargraph
58
61
  end
59
62
  end
60
63
 
64
+ # @param method [String]
65
+ # @return [String]
66
+ def example_group_documentation(method)
67
+ return unless Rspec::EXAMPLE_METHODS.include?(method)
68
+
69
+ yardoc = rspec_yardoc_tags_at("RSpec::Core::ExampleGroup.#{method}")
70
+
71
+ unless yardoc
72
+ Solargraph.logger.warn "[RSpec] YARD documentation not found for RSpec::Core::ExampleGroup.#{method}"
73
+ return
74
+ end
75
+
76
+ yardoc.docstring.all
77
+ end
78
+
79
+ # @param method [String]
80
+ # @return [YARD::CodeObjects::MethodObject, nil]
81
+ def rspec_yardoc_tags_at(method_path)
82
+ self.class.rspec_yardoc_tags.find { |tag| tag.path == method_path }
83
+ end
84
+
61
85
  # @return [Array<String>]
62
86
  def rspec_context_block_methods
63
87
  config.let_methods + Rspec::HOOK_METHODS + Rspec::EXAMPLE_METHODS
64
88
  end
89
+
90
+ # @return [Solargraph::Rspec::Config]
91
+ def config
92
+ Solargraph::Rspec::Convention.config
93
+ end
65
94
  end
66
95
  end
67
96
  end
@@ -1,58 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'walker_base'
3
+ require_relative 'base'
4
4
 
5
5
  module Solargraph
6
6
  module Rspec
7
7
  module Correctors
8
- # Sets the correct namespace binding for example group blocks (it, example, etc.) and
9
- # hook blocks (before, after, around)
10
- class ExampleAndHookBlocksBindingCorrector < WalkerBase
8
+ # RSpec executes example and hook blocks in the context of the example group (ie. describe blocks).
9
+ # This correctors sets the right bindings to those blocks.
10
+ class ExampleAndHookBlocksBindingCorrector < Base
11
11
  # @param source_map [Solargraph::SourceMap]
12
12
  # @return [void]
13
13
  def correct(source_map)
14
- rspec_walker.on_example_block do |block_ast|
15
- bind_closest_namespace(block_ast, source_map)
16
-
17
- yield [] if block_given?
14
+ rspec_walker.on_example_block do |location_range|
15
+ bind_closest_namespace(location_range, source_map)
18
16
  end
19
17
 
20
- rspec_walker.on_hook_block do |block_ast|
21
- bind_closest_namespace(block_ast, source_map)
22
-
23
- yield [] if block_given?
18
+ rspec_walker.on_hook_block do |location_range|
19
+ bind_closest_namespace(location_range, source_map)
24
20
  end
25
21
 
26
- rspec_walker.on_let_method do |let_method_ast|
27
- bind_closest_namespace(let_method_ast, source_map)
28
-
29
- yield [] if block_given?
22
+ rspec_walker.on_let_method do |_method_name, location_range|
23
+ bind_closest_namespace(location_range, source_map)
30
24
  end
31
25
 
32
- rspec_walker.on_blocks_in_examples do |block_ast|
33
- bind_closest_namespace(block_ast, source_map)
34
-
35
- yield [] if block_given?
26
+ rspec_walker.on_blocks_in_examples do |location_range|
27
+ bind_closest_namespace(location_range, source_map)
36
28
  end
37
29
 
38
- rspec_walker.on_subject do |subject_ast|
39
- bind_closest_namespace(subject_ast, source_map)
40
-
41
- yield [] if block_given?
30
+ rspec_walker.on_subject do |_method_name, location_range|
31
+ bind_closest_namespace(location_range, source_map)
42
32
  end
43
33
  end
44
34
 
45
35
  private
46
36
 
47
- # @param block_ast [Parser::AST::Node]
37
+ # @param location_range [Solargraph::Range]
48
38
  # @param source_map [Solargraph::SourceMap]
49
39
  # @return [void]
50
- def bind_closest_namespace(block_ast, source_map)
51
- namespace_pin = closest_namespace_pin(namespace_pins, block_ast.loc.line)
40
+ def bind_closest_namespace(location_range, source_map)
41
+ namespace_pin = closest_namespace_pin(namespace_pins, location_range.start.line)
52
42
  return unless namespace_pin
53
43
 
54
- original_block_pin = source_map.locate_block_pin(block_ast.location.begin.line,
55
- block_ast.location.begin.column)
44
+ original_block_pin = source_map.locate_block_pin(location_range.start.line,
45
+ location_range.start.column)
56
46
  original_block_pin_index = source_map.pins.index(original_block_pin)
57
47
  fixed_namespace_block_pin = Solargraph::Pin::Block.new(
58
48
  closure: example_run_method(namespace_pin),
@@ -67,7 +57,7 @@ module Solargraph
67
57
  # @param namespace_pin [Solargraph::Pin::Namespace]
68
58
  # @return [Solargraph::Pin::Method]
69
59
  def example_run_method(namespace_pin)
70
- Util.build_public_method(
60
+ PinFactory.build_public_method(
71
61
  namespace_pin,
72
62
  'run',
73
63
  # https://github.com/rspec/rspec-core/blob/main/lib/rspec/core/example.rb#L246
@@ -1,40 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'walker_base'
3
+ require_relative 'base'
4
4
 
5
5
  module Solargraph
6
6
  module Rspec
7
7
  module Correctors
8
8
  # Defines let-like methods in the example group block
9
- class LetMethodsCorrector < WalkerBase
9
+ class LetMethodsCorrector < Base
10
10
  # @param source_map [Solargraph::SourceMap]
11
11
  # @return [void]
12
12
  def correct(_source_map)
13
- rspec_walker.on_let_method do |ast|
14
- namespace_pin = closest_namespace_pin(namespace_pins, ast.loc.line)
13
+ rspec_walker.on_let_method do |let_name, location_range, fake_method_ast|
14
+ namespace_pin = closest_namespace_pin(namespace_pins, location_range.start.line)
15
15
  next unless namespace_pin
16
16
 
17
- pin = rspec_let_method(namespace_pin, ast)
18
- yield [pin] if block_given?
17
+ pin = rspec_let_method(namespace_pin, let_name, location_range, fake_method_ast)
18
+ add_pin(pin)
19
19
  end
20
20
  end
21
21
 
22
22
  private
23
23
 
24
24
  # @param namespace [Pin::Namespace]
25
- # @param ast [Parser::AST::Node]
25
+ # @param method_name [String]
26
+ # @param node [RubyVM::AbstractSyntaxTree::Node]
26
27
  # @param types [Array<String>, nil]
27
28
  # @return [Pin::Method, nil]
28
- def rspec_let_method(namespace, ast, types: nil)
29
- return unless ast.children
30
- return unless ast.children[2]&.children
31
-
32
- method_name = ast.children[2].children[0]&.to_s or return
33
- Util.build_public_method(
29
+ def rspec_let_method(namespace, method_name, location_range, node = nil, types: nil)
30
+ PinFactory.build_public_method(
34
31
  namespace,
35
32
  method_name,
33
+ node: node,
36
34
  types: types,
37
- location: Util.build_location(ast, namespace.filename),
35
+ location: PinFactory.build_location(location_range, namespace.filename),
38
36
  scope: :instance
39
37
  )
40
38
  end