solargraph-rspec 0.2.0 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/README.md +9 -4
- data/codecov.yml +13 -0
- data/lib/solargraph/rspec/convention.rb +17 -76
- data/lib/solargraph/rspec/correctors/base.rb +25 -2
- data/lib/solargraph/rspec/correctors/context_block_methods_corrector.rb +1 -3
- data/lib/solargraph/rspec/correctors/context_block_namespace_corrector.rb +5 -9
- data/lib/solargraph/rspec/correctors/described_class_corrector.rb +4 -3
- data/lib/solargraph/rspec/correctors/dsl_methods_corrector.rb +47 -18
- data/lib/solargraph/rspec/correctors/example_and_hook_blocks_binding_corrector.rb +4 -14
- data/lib/solargraph/rspec/correctors/let_methods_corrector.rb +3 -3
- data/lib/solargraph/rspec/correctors/subject_method_corrector.rb +42 -4
- data/lib/solargraph/rspec/spec_walker/fake_let_method.rb +12 -9
- data/lib/solargraph/rspec/spec_walker.rb +4 -0
- data/lib/solargraph/rspec/version.rb +1 -1
- metadata +10 -11
- data/lib/solargraph/rspec/correctors/implicit_subject_method_corrector.rb +0 -48
- data/lib/solargraph/rspec/correctors/walker_base.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b218c57b18c9c34c920dc8085633940b40980109acc0767e3819f2f460af7598
|
4
|
+
data.tar.gz: 8d33d3922c38de08dde380776138fb2eddee93f72aaaee1cd7ae4dce7610ac69
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d6afb3098eeaa24b1c169ba6993306b14008837ebfd267c30bfe74788cd5deecb7985d33037984f5ed698d259daf9c698dba19f4eed0e6a346f521f081a2d7a
|
7
|
+
data.tar.gz: 88699cf9f89421e1a0306d37ce912c1a1fc231cd722cc4338ec757efed7ca304791b1c2e3e3271b9cb057efe91f2d3db8fa22c70739b88569a0be59c9b0de229
|
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
7
7
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
|
+
### Fixed
|
11
|
+
|
12
|
+
- Suggest keeping `spec/**/*` in the `exclude` section of `.solargraph.yml` to avoid performance issues (see [commit](https://github.com/lekemula/solargraph-rspec/commit/3f0fc39e59e99bf9430e55c52ecb88650e49315e))
|
13
|
+
- Fix `let` definitions when do/end keywords overlap with body definition
|
14
|
+
```ruby
|
15
|
+
let(:todo) do # "do" keyword overlap
|
16
|
+
{
|
17
|
+
'todo' => 'end' # "end" keyword overlap
|
18
|
+
}
|
19
|
+
end
|
20
|
+
```
|
21
|
+
- Error handling in SpecWalker::FakeLetMethod
|
22
|
+
|
23
|
+
## [0.2.1] - 2024-06-09
|
24
|
+
|
25
|
+
### Added
|
26
|
+
|
27
|
+
- Documentation for `RSpec::ExampleGroups` DSL methods like `it`, `fit`, `example` etc.
|
28
|
+
|
29
|
+
### Fixed
|
30
|
+
|
31
|
+
- Fix nameless `subject` method completion inside nested `context` blocks
|
32
|
+
- (Hack-ish) Fix `described_class` type collision when `RSpec.describe SomeClassWithoutNamespace`
|
33
|
+
|
10
34
|
## [0.2.0] - 2024-05-20
|
11
35
|
|
12
36
|
### Added
|
data/README.md
CHANGED
@@ -34,14 +34,19 @@ Or add it to your Gemfile:
|
|
34
34
|
|
35
35
|
```ruby
|
36
36
|
group :development do
|
37
|
-
gem 'solargraph'
|
38
|
-
gem 'solargraph-rspec'
|
37
|
+
gem 'solargraph', require: false
|
38
|
+
gem 'solargraph-rspec', require: false
|
39
39
|
end
|
40
40
|
```
|
41
41
|
|
42
42
|
If you add them to your Gemfile, you'll have to tell your IDE plugin to use bundler to load the right version of solargraph.
|
43
43
|
|
44
|
-
Add `solargraph-rspec` to your `.solargraph.yml`
|
44
|
+
Add `solargraph-rspec` to your `.solargraph.yml` as a plugin.
|
45
|
+
|
46
|
+
> [!CAUTION]
|
47
|
+
> To avoid **performance issues**, please keep the `spec/**/*` directory in **exclude** list in the Solargraph configuration.
|
48
|
+
> That does not actually *exclude* the specs, but rather avoids pre-indexing the specs when Solargraph boots up, and only parses
|
49
|
+
> the specs on demand when opened in the editor, which is what we usually want.
|
45
50
|
|
46
51
|
(if you don't have a `.solargraph.yml` in your project root, you can run `solargraph config` to add one)
|
47
52
|
|
@@ -50,7 +55,7 @@ Add `solargraph-rspec` to your `.solargraph.yml` and remove the `spec` directory
|
|
50
55
|
include:
|
51
56
|
- "**/*.rb"
|
52
57
|
exclude:
|
53
|
-
|
58
|
+
+- spec/**/*
|
54
59
|
- test/**/*
|
55
60
|
- vendor/**/*
|
56
61
|
- ".bundle/**/*"
|
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,7 +8,6 @@ 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
12
|
require_relative 'pin_factory'
|
14
13
|
|
@@ -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,86 +115,17 @@ module Solargraph
|
|
105
115
|
|
106
116
|
rspec_walker = SpecWalker.new(source_map: source_map, config: config)
|
107
117
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
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(
|
125
|
-
namespace_pins: namespace_pins,
|
126
|
-
rspec_walker: rspec_walker
|
127
|
-
).correct(
|
128
|
-
source_map
|
129
|
-
) do |pins_to_add|
|
130
|
-
described_class_pin = pins_to_add.first
|
131
|
-
pins += pins_to_add
|
132
|
-
end
|
133
|
-
|
134
|
-
Correctors::LetMethodsCorrector.new(
|
135
|
-
namespace_pins: namespace_pins,
|
136
|
-
rspec_walker: rspec_walker
|
137
|
-
).correct(
|
138
|
-
source_map
|
139
|
-
) do |pins_to_add|
|
140
|
-
pins += pins_to_add
|
141
|
-
end
|
142
|
-
|
143
|
-
# @type [Pin::Method, nil]
|
144
|
-
subject_pin = nil
|
145
|
-
Correctors::SubjectMethodCorrector.new(
|
146
|
-
namespace_pins: namespace_pins,
|
147
|
-
rspec_walker: rspec_walker
|
148
|
-
).correct(
|
149
|
-
source_map
|
150
|
-
) do |pins_to_add|
|
151
|
-
subject_pin = pins_to_add.first
|
152
|
-
pins += pins_to_add
|
153
|
-
end
|
154
|
-
|
155
|
-
Correctors::ContextBlockMethodsCorrector.new(
|
156
|
-
namespace_pins: namespace_pins,
|
157
|
-
rspec_walker: rspec_walker
|
158
|
-
).correct(source_map) do |pins_to_add|
|
159
|
-
pins += pins_to_add
|
160
|
-
end
|
161
|
-
|
162
|
-
Correctors::DslMethodsCorrector.new(
|
163
|
-
namespace_pins: namespace_pins,
|
164
|
-
rspec_walker: rspec_walker,
|
165
|
-
config: config
|
166
|
-
).correct(
|
167
|
-
source_map
|
168
|
-
) do |pins_to_add|
|
169
|
-
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)
|
170
124
|
end
|
171
125
|
|
172
126
|
rspec_walker.walk!
|
173
127
|
pins += namespace_pins
|
174
128
|
|
175
|
-
# Implicit subject
|
176
|
-
if !subject_pin && described_class_pin
|
177
|
-
Correctors::ImplicitSubjectMethodCorrector.new(
|
178
|
-
namespace_pins: namespace_pins,
|
179
|
-
described_class_pin: described_class_pin
|
180
|
-
).correct(
|
181
|
-
source_map
|
182
|
-
) do |pins_to_add|
|
183
|
-
subject_pin = pins_to_add.first
|
184
|
-
pins += pins_to_add
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
129
|
if pins.any?
|
189
130
|
Solargraph.logger.debug(
|
190
131
|
"[RSpec] added #{pins.map(&:inspect)} to #{source_map.filename}"
|
@@ -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
|
-
|
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,6 +32,20 @@ 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(
|
@@ -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 <
|
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,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'base'
|
4
4
|
|
5
5
|
module Solargraph
|
6
6
|
module Rspec
|
7
7
|
module Correctors
|
8
|
-
#
|
9
|
-
class ContextBlockNamespaceCorrector <
|
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
12
|
# @param location_range [Solargraph::Range]
|
@@ -52,12 +52,8 @@ module Solargraph
|
|
52
52
|
)
|
53
53
|
|
54
54
|
namespace_pins << namespace_pin
|
55
|
-
|
56
|
-
|
57
|
-
namespace_include_pin,
|
58
|
-
namespace_extend_pin
|
59
|
-
]
|
60
|
-
end
|
55
|
+
|
56
|
+
add_pins(namespace_extend_pin, namespace_include_pin)
|
61
57
|
end
|
62
58
|
end
|
63
59
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'base'
|
4
4
|
|
5
5
|
module Solargraph
|
6
6
|
module Rspec
|
7
7
|
module Correctors
|
8
|
-
|
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)
|
@@ -14,7 +15,7 @@ module Solargraph
|
|
14
15
|
next unless namespace_pin
|
15
16
|
|
16
17
|
described_class_pin = rspec_described_class_method(namespace_pin, location_range, described_class_name)
|
17
|
-
|
18
|
+
add_pin(described_class_pin)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
@@ -1,44 +1,47 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'base'
|
4
|
+
require 'yard'
|
4
5
|
|
5
6
|
module Solargraph
|
6
7
|
module Rspec
|
7
8
|
module Correctors
|
8
|
-
|
9
|
-
|
10
|
-
# @
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
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
|
38
|
+
def methods_with_example_binding(namespace_pin)
|
37
39
|
rspec_context_block_methods.map do |method|
|
40
|
+
# TODO: Add location from YARD registry and documentation for other methods not just example group methods.
|
38
41
|
PinFactory.build_public_method(
|
39
42
|
namespace_pin,
|
40
43
|
method.to_s,
|
41
|
-
comments: ["@yieldself [#{namespace_pin.path}]"],
|
44
|
+
comments: [example_group_documentation(method), "@yieldself [#{namespace_pin.path}]"],
|
42
45
|
scope: :class
|
43
46
|
)
|
44
47
|
end
|
@@ -48,7 +51,7 @@ 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
|
54
|
+
def context_dsl_methods(namespace_pin)
|
52
55
|
Rspec::CONTEXT_METHODS.map do |method|
|
53
56
|
PinFactory.build_public_method(
|
54
57
|
namespace_pin,
|
@@ -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,44 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'base'
|
4
4
|
|
5
5
|
module Solargraph
|
6
6
|
module Rspec
|
7
7
|
module Correctors
|
8
|
-
#
|
9
|
-
#
|
10
|
-
class ExampleAndHookBlocksBindingCorrector <
|
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
14
|
rspec_walker.on_example_block do |location_range|
|
15
15
|
bind_closest_namespace(location_range, source_map)
|
16
|
-
|
17
|
-
yield [] if block_given?
|
18
16
|
end
|
19
17
|
|
20
18
|
rspec_walker.on_hook_block do |location_range|
|
21
19
|
bind_closest_namespace(location_range, source_map)
|
22
|
-
|
23
|
-
yield [] if block_given?
|
24
20
|
end
|
25
21
|
|
26
22
|
rspec_walker.on_let_method do |_method_name, location_range|
|
27
23
|
bind_closest_namespace(location_range, source_map)
|
28
|
-
|
29
|
-
yield [] if block_given?
|
30
24
|
end
|
31
25
|
|
32
26
|
rspec_walker.on_blocks_in_examples do |location_range|
|
33
27
|
bind_closest_namespace(location_range, source_map)
|
34
|
-
|
35
|
-
yield [] if block_given?
|
36
28
|
end
|
37
29
|
|
38
30
|
rspec_walker.on_subject do |_method_name, location_range|
|
39
31
|
bind_closest_namespace(location_range, source_map)
|
40
|
-
|
41
|
-
yield [] if block_given?
|
42
32
|
end
|
43
33
|
end
|
44
34
|
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
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 <
|
9
|
+
class LetMethodsCorrector < Base
|
10
10
|
# @param source_map [Solargraph::SourceMap]
|
11
11
|
# @return [void]
|
12
12
|
def correct(_source_map)
|
@@ -15,7 +15,7 @@ module Solargraph
|
|
15
15
|
next unless namespace_pin
|
16
16
|
|
17
17
|
pin = rspec_let_method(namespace_pin, let_name, location_range, fake_method_ast)
|
18
|
-
|
18
|
+
add_pin(pin)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -11,14 +11,52 @@ module Solargraph
|
|
11
11
|
# @return [void]
|
12
12
|
def correct(_source_map)
|
13
13
|
rspec_walker.on_subject do |subject_name, location_range, fake_method_ast|
|
14
|
-
next unless subject_name
|
15
|
-
|
16
14
|
namespace_pin = closest_namespace_pin(namespace_pins, location_range.start.line)
|
17
15
|
next unless namespace_pin
|
18
16
|
|
19
|
-
subject_pin =
|
20
|
-
|
17
|
+
subject_pin = rspec_subject_method(namespace_pin, subject_name, location_range, fake_method_ast)
|
18
|
+
add_pin(subject_pin)
|
21
19
|
end
|
20
|
+
|
21
|
+
rspec_walker.after_walk do
|
22
|
+
next unless described_class_pin
|
23
|
+
|
24
|
+
namespace_pin = closest_namespace_pin(namespace_pins, described_class_pin.location.range.start.line)
|
25
|
+
|
26
|
+
add_pin(implicit_subject_pin(described_class_pin, namespace_pin)) if namespace_pin
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# @return [Pin::Method, nil]
|
33
|
+
def described_class_pin
|
34
|
+
@described_class_pin ||= added_pins.find { |pin| pin.is_a?(Pin::Method) && pin.name == 'described_class' }
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param namespace_pin [Pin::Namespace]
|
38
|
+
# @param subject_name [String, nil]
|
39
|
+
# @param location_range [Solargraph::Range]
|
40
|
+
# @param fake_method_ast [Parser::AST::Node]
|
41
|
+
# @return [Pin::Method]
|
42
|
+
def rspec_subject_method(namespace_pin, subject_name, location_range, fake_method_ast)
|
43
|
+
method_name = subject_name || 'subject'
|
44
|
+
rspec_let_method(namespace_pin, method_name, location_range, fake_method_ast)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param described_class_pin [Pin::Method]
|
48
|
+
# @param namespace_pin [Pin::Namespace]
|
49
|
+
# @return [Pin::Method]
|
50
|
+
def implicit_subject_pin(described_class_pin, namespace_pin)
|
51
|
+
described_class = described_class_pin.return_type.first.subtypes.first.name
|
52
|
+
|
53
|
+
PinFactory.build_public_method(
|
54
|
+
namespace_pin,
|
55
|
+
'subject',
|
56
|
+
types: ["::#{described_class}"],
|
57
|
+
location: described_class_pin.location,
|
58
|
+
scope: :instance
|
59
|
+
)
|
22
60
|
end
|
23
61
|
end
|
24
62
|
end
|
@@ -4,18 +4,18 @@ module Solargraph
|
|
4
4
|
module Rspec
|
5
5
|
class SpecWalker
|
6
6
|
class FakeLetMethod
|
7
|
-
|
8
|
-
|
9
|
-
/{(.*)}/m
|
10
|
-
)
|
7
|
+
MATCH_DO_END = /.*? do(.*)end/m.freeze
|
8
|
+
MATCH_CURLY = /{(.*)}/m.freeze
|
11
9
|
|
12
10
|
# @param block_ast [RubyVM::AbstractSyntaxTree::Node]
|
13
|
-
# @return [RubyVM::AbstractSyntaxTree::Node]
|
11
|
+
# @return [RubyVM::AbstractSyntaxTree::Node, nil]
|
14
12
|
def self.transform_block(block_ast, code, method_name = nil)
|
15
13
|
method_name ||= NodeTypes.let_method_name(block_ast)
|
16
14
|
block_body = block_ast.children[1]
|
17
|
-
|
18
|
-
|
15
|
+
let_definition_code = code.lines[block_body.first_lineno - 1..block_body.last_lineno - 1].join
|
16
|
+
match_do_end = let_definition_code.match(MATCH_DO_END)&.captures&.first || ''
|
17
|
+
match_curly = let_definition_code.match(MATCH_CURLY)&.captures&.first || ''
|
18
|
+
method_body = [match_do_end, match_curly].max_by(&:length).strip
|
19
19
|
|
20
20
|
ast = RubyVM::AbstractSyntaxTree.parse <<~RUBY
|
21
21
|
def #{method_name}
|
@@ -24,8 +24,11 @@ module Solargraph
|
|
24
24
|
RUBY
|
25
25
|
|
26
26
|
ast.children[2]
|
27
|
-
rescue SyntaxError
|
28
|
-
|
27
|
+
rescue SyntaxError => e
|
28
|
+
Solargraph.logger.warn "[RSpec] Failed to build fake let method: #{e.message}, \
|
29
|
+
\n\nlet_definition_code: \n```\n#{let_definition_code}\n```, \
|
30
|
+
\n\nmethod_body: \n```\n#{method_body}\n```, \
|
31
|
+
\nast: #{block_ast.inspect}"
|
29
32
|
ensure
|
30
33
|
nil
|
31
34
|
end
|
@@ -201,6 +201,10 @@ module Solargraph
|
|
201
201
|
block_name = RspecContextNamespace.from_block_ast(block_ast)
|
202
202
|
next unless block_name
|
203
203
|
|
204
|
+
# @HACK: When we describe `SomeClass` without a namespace, Solargraph confuses described_class with the
|
205
|
+
# `RSpec::ExampleGroups::SomeClass` constant. To avoid this, we append the root namespace with "Test"
|
206
|
+
block_name = "Test#{block_name}" if parent_namespace == Rspec::ROOT_NAMESPACE
|
207
|
+
|
204
208
|
parent_namespace = namespace_name = "#{parent_namespace}::#{block_name}"
|
205
209
|
block&.call(namespace_name, block_ast)
|
206
210
|
next parent_namespace
|
metadata
CHANGED
@@ -1,35 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solargraph-rspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lekë Mula
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: solargraph
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 0.49.0
|
20
17
|
- - "~>"
|
21
18
|
- !ruby/object:Gem::Version
|
22
19
|
version: '0.49'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.49.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 0.49.0
|
30
27
|
- - "~>"
|
31
28
|
- !ruby/object:Gem::Version
|
32
29
|
version: '0.49'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.49.0
|
33
33
|
description: RSpec is a testing tool of choice for many Ruby developers. This plugin
|
34
34
|
provides code completion and other features for RSpec files in Solargraph.
|
35
35
|
email:
|
@@ -45,6 +45,7 @@ files:
|
|
45
45
|
- LICENSE.txt
|
46
46
|
- README.md
|
47
47
|
- Rakefile
|
48
|
+
- codecov.yml
|
48
49
|
- lib/solargraph-rspec.rb
|
49
50
|
- lib/solargraph/rspec/config.rb
|
50
51
|
- lib/solargraph/rspec/convention.rb
|
@@ -54,10 +55,8 @@ files:
|
|
54
55
|
- lib/solargraph/rspec/correctors/described_class_corrector.rb
|
55
56
|
- lib/solargraph/rspec/correctors/dsl_methods_corrector.rb
|
56
57
|
- lib/solargraph/rspec/correctors/example_and_hook_blocks_binding_corrector.rb
|
57
|
-
- lib/solargraph/rspec/correctors/implicit_subject_method_corrector.rb
|
58
58
|
- lib/solargraph/rspec/correctors/let_methods_corrector.rb
|
59
59
|
- lib/solargraph/rspec/correctors/subject_method_corrector.rb
|
60
|
-
- lib/solargraph/rspec/correctors/walker_base.rb
|
61
60
|
- lib/solargraph/rspec/pin_factory.rb
|
62
61
|
- lib/solargraph/rspec/spec_walker.rb
|
63
62
|
- lib/solargraph/rspec/spec_walker/fake_let_method.rb
|
@@ -90,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
89
|
- !ruby/object:Gem::Version
|
91
90
|
version: '0'
|
92
91
|
requirements: []
|
93
|
-
rubygems_version: 3.
|
92
|
+
rubygems_version: 3.4.10
|
94
93
|
signing_key:
|
95
94
|
specification_version: 4
|
96
95
|
summary: Solargraph plugin supporting RSpec code completion
|
@@ -1,48 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'let_methods_corrector'
|
4
|
-
|
5
|
-
module Solargraph
|
6
|
-
module Rspec
|
7
|
-
module Correctors
|
8
|
-
# Defines let-like methods in the example group block
|
9
|
-
class ImplicitSubjectMethodCorrector < Base
|
10
|
-
# @return [Pin::Method]
|
11
|
-
attr_reader :described_class_pin
|
12
|
-
|
13
|
-
# @param namespace_pins [Array<Pin::Namespace>]
|
14
|
-
# @param described_class_pin [Pin::Method]
|
15
|
-
def initialize(namespace_pins:, described_class_pin:)
|
16
|
-
super(namespace_pins: namespace_pins)
|
17
|
-
|
18
|
-
@described_class_pin = described_class_pin
|
19
|
-
end
|
20
|
-
|
21
|
-
# @param source_map [Solargraph::SourceMap]
|
22
|
-
# @return [void]
|
23
|
-
def correct(_source_map)
|
24
|
-
namespace_pin = closest_namespace_pin(namespace_pins, described_class_pin.location.range.start.line)
|
25
|
-
|
26
|
-
yield [implicit_subject_pin(described_class_pin, namespace_pin)] if block_given? && namespace_pin
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
# @param described_class_pin [Pin::Method]
|
32
|
-
# @param namespace_pin [Pin::Namespace]
|
33
|
-
# @return [Pin::Method]
|
34
|
-
def implicit_subject_pin(described_class_pin, namespace_pin)
|
35
|
-
described_class = described_class_pin.return_type.first.subtypes.first.name
|
36
|
-
|
37
|
-
PinFactory.build_public_method(
|
38
|
-
namespace_pin,
|
39
|
-
'subject',
|
40
|
-
types: ["::#{described_class}"],
|
41
|
-
location: described_class_pin.location,
|
42
|
-
scope: :instance
|
43
|
-
)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'base'
|
4
|
-
|
5
|
-
# A corrector that walks through RSpec AST nodes and corrects them
|
6
|
-
module Solargraph
|
7
|
-
module Rspec
|
8
|
-
module Correctors
|
9
|
-
# A corrector of RSpec parsed pins by Solargraph
|
10
|
-
# @abstract
|
11
|
-
class WalkerBase < Base
|
12
|
-
# @return [Array<Solargraph::Pin::Namespace>]
|
13
|
-
attr_reader :namespace_pins
|
14
|
-
|
15
|
-
# @return [Solargraph::Rspec::SpecWalker]
|
16
|
-
attr_reader :rspec_walker
|
17
|
-
|
18
|
-
# @param namespace_pins [Array<Solargraph::Pin::Base>]
|
19
|
-
# @param rspec_walker [Solargraph::Rspec::SpecWalker]
|
20
|
-
def initialize(namespace_pins:, rspec_walker:)
|
21
|
-
super(namespace_pins: namespace_pins)
|
22
|
-
@rspec_walker = rspec_walker
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|