solargraph-rspec 0.1.0 β†’ 0.2.0

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: b29106f92a5279085cce258a7aabc92070d5452446a8f5a0b9c141d2a3d5a52d
4
- data.tar.gz: a153e3a43ff36c494484ecef9e7ef4f31066b0c002f0c3e16505a3357231591f
3
+ metadata.gz: 1f73a95cc73aa3ce52cff1e5e4e8e06509f3a59ccf6a3371b9087fad38e135b0
4
+ data.tar.gz: 221342fb0163f67fce1648aa4b14310b31907aacc9637def0b61e690b8ff750e
5
5
  SHA512:
6
- metadata.gz: 7c12a1454723f6acfe6bafcb856ff300734d27429d6ee08f053f2c05b30f7ff3885bb595ce14fb360bbfeec1cbf9339938a52cfa2f63874fce4cbd2d6efacbcf
7
- data.tar.gz: 3b81a6a82e580bc0e5ff86a0aeb66d61f6f9c8a8e7191ac0df52a31ac482b9dc774cd10b43d881babf80fdd6e60c93dc87a25a7f72ad296aea6d57743c550055
6
+ metadata.gz: 47f84a714dc459f67e354b68ff1c037e0ee9170a364db3fb4aa8e7a04cef1ce81952fade0a109a41de91f57b0b18201d3d8ab95b901f94de679357688bc9e41f
7
+ data.tar.gz: a5bff062303a4fd717315083944c19dbe1c21a94ee795e9f29d5e2971d574038bb75677c596645dacd5861f5f624a7a36a93347c48e443a549ab7decc387dae3
data/CHANGELOG.md CHANGED
@@ -7,7 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- -
10
+ ## [0.2.0] - 2024-05-20
11
+
12
+ ### Added
13
+
14
+ - `let` and `subject` type inference πŸš€ (Resolves: [Issue #1](https://github.com/lekemula/solargraph-rspec/issues/1))
15
+
16
+ ### Changed
17
+
18
+ - Migrate from `parser` gem to using ruby's built-in RubyVM::AbstractSyntaxTree ([see why](https://github.com/castwide/solargraph/issues/522#issuecomment-993016664))
19
+
20
+ ### Fixed
21
+
22
+ - Fix subject without name block completion: `subject { ... }`
23
+ - Fix subject return class overlap with `Rspec::ExampleGroups::` when class has no namespace
24
+
25
+ ## [0.1.1] - 2024-05-13
26
+
27
+ ### Removed
28
+ - Removed redundant `active_support` dependency ([Issue #2](https://github.com/lekemula/solargraph-rspec/issues/2))
29
+
30
+ ### Fixed
31
+ - Fixed completions inside `subject` and `subject!` blocks
11
32
 
12
33
  ## [0.1.0] - 2024-05-11 (First Release πŸŽ‰)
13
34
 
data/README.md CHANGED
@@ -1,20 +1,24 @@
1
- # Solargraph::Rspec - A Solargraph plugin for better RSpec support
1
+ # Solargraph::Rspec - A [Solargraph](https://solargraph.org/) plugin for better [RSpec](https://rspec.info/) support
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/solargraph-rspec.svg)](https://badge.fury.io/rb/solargraph-rspec)
3
4
  ![Tests](https://github.com/lekemula/solargraph-rspec/actions/workflows/ruby.yml/badge.svg)
4
5
  [![codecov](https://codecov.io/gh/lekemula/solargraph-rspec/graph/badge.svg?token=FH7ER8ZDPW)](https://codecov.io/gh/lekemula/solargraph-rspec)
5
6
 
6
7
 
7
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.
8
9
 
9
- 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:
10
11
  - `describe` and `it` methods completion
11
12
  - memoized `let` and `let!` methods completion
12
13
  - implicit and explicit `subject` methods
13
14
  - `described_class` with appropriate type inference
14
15
  - `RSpec::Matchers` methods completion
16
+ - type inference πŸš€
15
17
  - and more to come...
16
18
 
17
- ![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
+
18
22
 
19
23
  ## Installation
20
24
 
@@ -10,7 +10,7 @@ require_relative 'correctors/subject_method_corrector'
10
10
  require_relative 'correctors/context_block_methods_corrector'
11
11
  require_relative 'correctors/implicit_subject_method_corrector'
12
12
  require_relative 'correctors/dsl_methods_corrector'
13
- require_relative 'util'
13
+ require_relative 'pin_factory'
14
14
 
15
15
  module Solargraph
16
16
  module Rspec
@@ -18,6 +18,7 @@ module Solargraph
18
18
  HELPER_MODULES = ['RSpec::Matchers'].freeze
19
19
  HOOK_METHODS = %w[before after around].freeze
20
20
  LET_METHODS = %w[let let!].freeze
21
+ SUBJECT_METHODS = %w[subject subject!].freeze
21
22
  EXAMPLE_METHODS = %w[
22
23
  example
23
24
  it
@@ -120,14 +121,20 @@ module Solargraph
120
121
 
121
122
  # @type [Pin::Method, nil]
122
123
  described_class_pin = nil
123
- Correctors::DescribedClassCorrector.new(namespace_pins: namespace_pins, rspec_walker: rspec_walker).correct(
124
+ Correctors::DescribedClassCorrector.new(
125
+ namespace_pins: namespace_pins,
126
+ rspec_walker: rspec_walker
127
+ ).correct(
124
128
  source_map
125
129
  ) do |pins_to_add|
126
130
  described_class_pin = pins_to_add.first
127
131
  pins += pins_to_add
128
132
  end
129
133
 
130
- Correctors::LetMethodsCorrector.new(namespace_pins: namespace_pins, rspec_walker: rspec_walker).correct(
134
+ Correctors::LetMethodsCorrector.new(
135
+ namespace_pins: namespace_pins,
136
+ rspec_walker: rspec_walker
137
+ ).correct(
131
138
  source_map
132
139
  ) do |pins_to_add|
133
140
  pins += pins_to_add
@@ -135,7 +142,10 @@ module Solargraph
135
142
 
136
143
  # @type [Pin::Method, nil]
137
144
  subject_pin = nil
138
- Correctors::SubjectMethodCorrector.new(namespace_pins: namespace_pins, rspec_walker: rspec_walker).correct(
145
+ Correctors::SubjectMethodCorrector.new(
146
+ namespace_pins: namespace_pins,
147
+ rspec_walker: rspec_walker
148
+ ).correct(
139
149
  source_map
140
150
  ) do |pins_to_add|
141
151
  subject_pin = pins_to_add.first
@@ -198,7 +208,7 @@ module Solargraph
198
208
  # @return [Array<Pin::Base>]
199
209
  def include_helper_pins(helper_modules: HELPER_MODULES)
200
210
  helper_modules.map do |helper_module|
201
- Util.build_module_include(
211
+ PinFactory.build_module_include(
202
212
  root_example_group_namespace_pin,
203
213
  helper_module,
204
214
  root_example_group_namespace_pin.location
@@ -215,7 +225,7 @@ module Solargraph
215
225
  def root_example_group_namespace_pin
216
226
  Solargraph::Pin::Namespace.new(
217
227
  name: ROOT_NAMESPACE,
218
- location: Util.dummy_location('lib/rspec/core/example_group.rb')
228
+ location: PinFactory.dummy_location('lib/rspec/core/example_group.rb')
219
229
  )
220
230
  end
221
231
  end
@@ -27,7 +27,7 @@ module Solargraph
27
27
  def root_example_group_namespace_pin
28
28
  Solargraph::Pin::Namespace.new(
29
29
  name: ROOT_NAMESPACE,
30
- location: Util.dummy_location('lib/rspec/core/example_group.rb')
30
+ location: PinFactory.dummy_location('lib/rspec/core/example_group.rb')
31
31
  )
32
32
  end
33
33
 
@@ -9,10 +9,11 @@ module Solargraph
9
9
  class ContextBlockNamespaceCorrector < WalkerBase
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,7 +45,7 @@ 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
@@ -9,11 +9,11 @@ module Solargraph
9
9
  # @param source_map [Solargraph::SourceMap]
10
10
  # @return [void]
11
11
  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)
12
+ rspec_walker.on_described_class do |described_class_name, location_range|
13
+ namespace_pin = closest_namespace_pin(namespace_pins, location_range.start.line)
14
14
  next unless namespace_pin
15
15
 
16
- described_class_pin = rspec_described_class_method(namespace_pin, ast, described_class_name)
16
+ described_class_pin = rspec_described_class_method(namespace_pin, location_range, described_class_name)
17
17
  yield [described_class_pin].compact if block_given?
18
18
  end
19
19
  end
@@ -21,15 +21,15 @@ module Solargraph
21
21
  private
22
22
 
23
23
  # @param namespace [Pin::Namespace]
24
- # @param ast [Parser::AST::Node]
24
+ # @param location_range [Solargraph::Range]
25
25
  # @param described_class_name [String]
26
26
  # @return [Pin::Method, nil]
27
- def rspec_described_class_method(namespace, ast, described_class_name)
28
- Util.build_public_method(
27
+ def rspec_described_class_method(namespace, location_range, described_class_name)
28
+ PinFactory.build_public_method(
29
29
  namespace,
30
30
  'described_class',
31
- types: ["Class<#{described_class_name}>"],
32
- location: Util.build_location(ast, namespace.filename),
31
+ types: ["Class<::#{described_class_name}>"],
32
+ location: PinFactory.build_location(location_range, namespace.filename),
33
33
  scope: :instance
34
34
  )
35
35
  end
@@ -35,7 +35,7 @@ module Solargraph
35
35
  # @return [Array<Solargraph::Pin::Method>]
36
36
  def add_methods_with_example_binding(namespace_pin)
37
37
  rspec_context_block_methods.map do |method|
38
- Util.build_public_method(
38
+ PinFactory.build_public_method(
39
39
  namespace_pin,
40
40
  method.to_s,
41
41
  comments: ["@yieldself [#{namespace_pin.path}]"], # Fixes the binding of the block to the correct class
@@ -50,7 +50,7 @@ module Solargraph
50
50
  # @return [Array<Solargraph::Pin::Base>]
51
51
  def add_context_dsl_methods(namespace_pin)
52
52
  Rspec::CONTEXT_METHODS.map do |method|
53
- Util.build_public_method(
53
+ PinFactory.build_public_method(
54
54
  namespace_pin,
55
55
  method.to_s,
56
56
  scope: :class
@@ -11,26 +11,32 @@ module Solargraph
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)
14
+ rspec_walker.on_example_block do |location_range|
15
+ bind_closest_namespace(location_range, source_map)
16
16
 
17
17
  yield [] if block_given?
18
18
  end
19
19
 
20
- rspec_walker.on_hook_block do |block_ast|
21
- bind_closest_namespace(block_ast, source_map)
20
+ rspec_walker.on_hook_block do |location_range|
21
+ bind_closest_namespace(location_range, source_map)
22
22
 
23
23
  yield [] if block_given?
24
24
  end
25
25
 
26
- rspec_walker.on_let_method do |let_method_ast|
27
- bind_closest_namespace(let_method_ast, source_map)
26
+ rspec_walker.on_let_method do |_method_name, location_range|
27
+ bind_closest_namespace(location_range, source_map)
28
28
 
29
29
  yield [] if block_given?
30
30
  end
31
31
 
32
- rspec_walker.on_blocks_in_examples do |block_ast|
33
- bind_closest_namespace(block_ast, source_map)
32
+ rspec_walker.on_blocks_in_examples do |location_range|
33
+ bind_closest_namespace(location_range, source_map)
34
+
35
+ yield [] if block_given?
36
+ end
37
+
38
+ rspec_walker.on_subject do |_method_name, location_range|
39
+ bind_closest_namespace(location_range, source_map)
34
40
 
35
41
  yield [] if block_given?
36
42
  end
@@ -38,15 +44,15 @@ module Solargraph
38
44
 
39
45
  private
40
46
 
41
- # @param block_ast [Parser::AST::Node]
47
+ # @param location_range [Solargraph::Range]
42
48
  # @param source_map [Solargraph::SourceMap]
43
49
  # @return [void]
44
- def bind_closest_namespace(block_ast, source_map)
45
- namespace_pin = closest_namespace_pin(namespace_pins, block_ast.loc.line)
50
+ def bind_closest_namespace(location_range, source_map)
51
+ namespace_pin = closest_namespace_pin(namespace_pins, location_range.start.line)
46
52
  return unless namespace_pin
47
53
 
48
- original_block_pin = source_map.locate_block_pin(block_ast.location.begin.line,
49
- block_ast.location.begin.column)
54
+ original_block_pin = source_map.locate_block_pin(location_range.start.line,
55
+ location_range.start.column)
50
56
  original_block_pin_index = source_map.pins.index(original_block_pin)
51
57
  fixed_namespace_block_pin = Solargraph::Pin::Block.new(
52
58
  closure: example_run_method(namespace_pin),
@@ -61,7 +67,7 @@ module Solargraph
61
67
  # @param namespace_pin [Solargraph::Pin::Namespace]
62
68
  # @return [Solargraph::Pin::Method]
63
69
  def example_run_method(namespace_pin)
64
- Util.build_public_method(
70
+ PinFactory.build_public_method(
65
71
  namespace_pin,
66
72
  'run',
67
73
  # https://github.com/rspec/rspec-core/blob/main/lib/rspec/core/example.rb#L246
@@ -34,10 +34,10 @@ module Solargraph
34
34
  def implicit_subject_pin(described_class_pin, namespace_pin)
35
35
  described_class = described_class_pin.return_type.first.subtypes.first.name
36
36
 
37
- Util.build_public_method(
37
+ PinFactory.build_public_method(
38
38
  namespace_pin,
39
39
  'subject',
40
- types: [described_class],
40
+ types: ["::#{described_class}"],
41
41
  location: described_class_pin.location,
42
42
  scope: :instance
43
43
  )
@@ -10,11 +10,11 @@ module Solargraph
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)
17
+ pin = rspec_let_method(namespace_pin, let_name, location_range, fake_method_ast)
18
18
  yield [pin] if block_given?
19
19
  end
20
20
  end
@@ -22,19 +22,17 @@ module Solargraph
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
@@ -10,11 +10,13 @@ module Solargraph
10
10
  # @param source_map [Solargraph::SourceMap]
11
11
  # @return [void]
12
12
  def correct(_source_map)
13
- rspec_walker.on_subject do |ast|
14
- namespace_pin = closest_namespace_pin(namespace_pins, ast.loc.line)
13
+ rspec_walker.on_subject do |subject_name, location_range, fake_method_ast|
14
+ next unless subject_name
15
+
16
+ namespace_pin = closest_namespace_pin(namespace_pins, location_range.start.line)
15
17
  next unless namespace_pin
16
18
 
17
- subject_pin = rspec_let_method(namespace_pin, ast)
19
+ subject_pin = rspec_let_method(namespace_pin, subject_name, location_range, fake_method_ast)
18
20
  yield [subject_pin].compact if block_given?
19
21
  end
20
22
  end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Credits: This file is a copy of the file from the solargraph-rspec gem
4
+
5
+ module Solargraph
6
+ module Rspec
7
+ # Factory class for building pins and references.
8
+ module PinFactory
9
+ # @param namespace [Solargraph::Pin::Namespace]
10
+ # @param name [String]
11
+ # @param types [Array<String>]
12
+ # @param location [Solargraph::Location]
13
+ # @param comments [Array<String>]
14
+ # @param attribute [Boolean]
15
+ # @param scope [:instance, :class]
16
+ # @return [Solargraph::Pin::Method]
17
+ def self.build_public_method(
18
+ namespace,
19
+ name,
20
+ types: nil,
21
+ location: nil,
22
+ comments: [],
23
+ attribute: false,
24
+ scope: :instance,
25
+ node: nil
26
+ )
27
+ opts = {
28
+ name: name,
29
+ location: location,
30
+ closure: namespace,
31
+ scope: scope,
32
+ attribute: attribute,
33
+ comments: [],
34
+ node: node
35
+ }
36
+
37
+ comments << "@return [#{types.join(",")}]" if types
38
+
39
+ opts[:comments] = comments.join("\n")
40
+
41
+ Solargraph::Pin::Method.new(**opts)
42
+ end
43
+
44
+ # @param namespace [Solargraph::Pin::Namespace]
45
+ # @param name [String]
46
+ # @param location [Solargraph::Location]
47
+ # @return [Solargraph::Pin::Reference::Include]
48
+ def self.build_module_include(namespace, module_name, location)
49
+ Solargraph::Pin::Reference::Include.new(
50
+ closure: namespace,
51
+ name: module_name,
52
+ location: location
53
+ )
54
+ end
55
+
56
+ # @param namespace [Solargraph::Pin::Namespace]
57
+ # @param module_name [String]
58
+ # @param location [Solargraph::Location]
59
+ # @return [Solargraph::Pin::Reference::Extend]
60
+ def self.build_module_extend(namespace, module_name, location)
61
+ Solargraph::Pin::Reference::Extend.new(
62
+ closure: namespace,
63
+ name: module_name,
64
+ location: location
65
+ )
66
+ end
67
+
68
+ # @param path [String]
69
+ # @return [Solargraph::Location]
70
+ def self.dummy_location(path)
71
+ Solargraph::Location.new(
72
+ File.expand_path(path),
73
+ Solargraph::Range.from_to(0, 0, 0, 0)
74
+ )
75
+ end
76
+
77
+ # @param ast [RubyVM::AbstractSyntaxTree::Node]
78
+ # @see [RubyVM::AbstractSyntaxTree::NodeWrapper] - for why we need -1 for lineno
79
+ # @return [Solargraph::Range]
80
+ def self.build_location_range(ast)
81
+ Solargraph::Range.from_to(
82
+ ast.first_lineno - 1,
83
+ ast.first_column,
84
+ ast.last_lineno - 1,
85
+ ast.last_column
86
+ )
87
+ end
88
+
89
+ # @param location_range [Solargraph::Range]
90
+ # @param path [String]
91
+ # @return [Solargraph::Location]
92
+ def self.build_location(location_range, path)
93
+ Solargraph::Location.new(
94
+ File.expand_path(path),
95
+ location_range
96
+ )
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Rspec
5
+ class SpecWalker
6
+ class FakeLetMethod
7
+ MATCH_BODY = Regexp.union(
8
+ /do(.*)end/m,
9
+ /{(.*)}/m
10
+ )
11
+
12
+ # @param block_ast [RubyVM::AbstractSyntaxTree::Node]
13
+ # @return [RubyVM::AbstractSyntaxTree::Node]
14
+ def self.transform_block(block_ast, code, method_name = nil)
15
+ method_name ||= NodeTypes.let_method_name(block_ast)
16
+ block_body = block_ast.children[1]
17
+ matches = code.lines[block_body.first_lineno - 1..block_body.last_lineno - 1].join.match(MATCH_BODY)
18
+ method_body = (matches[1] || matches[2]).strip
19
+
20
+ ast = RubyVM::AbstractSyntaxTree.parse <<~RUBY
21
+ def #{method_name}
22
+ #{method_body}
23
+ end
24
+ RUBY
25
+
26
+ ast.children[2]
27
+ rescue SyntaxError
28
+ raise "Failed to build fake let method: #{block_ast.inspect}, message: #{e.message}"
29
+ ensure
30
+ nil
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Rspec
5
+ class SpecWalker
6
+ class FullConstantName
7
+ class << self
8
+ # @param ast [RubyVM::AbstractSyntaxTree::Node]
9
+ # @return [String]
10
+ def from_ast(ast)
11
+ raise 'Node is not a constant' unless NodeTypes.a_constant?(ast)
12
+
13
+ if ast.type == :CONST
14
+ ast.children[0].to_s
15
+ elsif ast.type == :COLON2
16
+ name = ast.children[1].to_s
17
+ "#{from_ast(ast.children[0])}::#{name}"
18
+ end
19
+ end
20
+
21
+ def from_context_block_ast(block_ast)
22
+ ast = NodeTypes.context_description_node(block_ast)
23
+ from_ast(ast)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Rspec
5
+ class SpecWalker
6
+ class NodeTypes
7
+ # @param ast [RubyVM::AbstractSyntaxTree::Node]
8
+ # @return [Boolean]
9
+ def self.a_block?(ast)
10
+ return false unless ast.is_a?(RubyVM::AbstractSyntaxTree::Node)
11
+
12
+ %i[ITER LAMBDA].include?(ast.type)
13
+ end
14
+
15
+ # @param ast [RubyVM::AbstractSyntaxTree::Node]
16
+ # @return [Boolean]
17
+ def self.a_context_block?(block_ast)
18
+ Solargraph::Rspec::CONTEXT_METHODS.include?(method_with_block_name(block_ast))
19
+ end
20
+
21
+ # @param ast [RubyVM::AbstractSyntaxTree::Node]
22
+ # @return [Boolean]
23
+ def self.a_subject_block?(block_ast)
24
+ Solargraph::Rspec::SUBJECT_METHODS.include?(method_with_block_name(block_ast))
25
+ end
26
+
27
+ # @param ast [RubyVM::AbstractSyntaxTree::Node]
28
+ # @return [Boolean]
29
+ def self.a_example_block?(block_ast)
30
+ Solargraph::Rspec::EXAMPLE_METHODS.include?(method_with_block_name(block_ast))
31
+ end
32
+
33
+ # @param ast [RubyVM::AbstractSyntaxTree::Node]
34
+ # @param config [Config]
35
+ # @return [Boolean]
36
+ def self.a_let_block?(block_ast, config)
37
+ config.let_methods.map(&:to_s).include?(method_with_block_name(block_ast))
38
+ end
39
+
40
+ # @param ast [RubyVM::AbstractSyntaxTree::Node]
41
+ # @return [Boolean]
42
+ def self.a_hook_block?(block_ast)
43
+ Solargraph::Rspec::HOOK_METHODS.include?(method_with_block_name(block_ast))
44
+ end
45
+
46
+ def self.a_constant?(ast)
47
+ %i[CONST COLON2].include?(ast.type)
48
+ end
49
+
50
+ # @param block_ast [RubyVM::AbstractSyntaxTree::Node]
51
+ # @return [String, nil]
52
+ def self.method_with_block_name(block_ast)
53
+ return nil unless a_block?(block_ast)
54
+
55
+ method_call = %i[CALL FCALL].include?(block_ast.children[0].type)
56
+ return nil unless method_call
57
+
58
+ block_ast.children[0].children.select { |child| child.is_a?(Symbol) }.first&.to_s
59
+ end
60
+
61
+ # @param block_ast [RubyVM::AbstractSyntaxTree::Node]
62
+ # @return [RubyVM::AbstractSyntaxTree::Node]
63
+ def self.context_description_node(block_ast)
64
+ return nil unless a_context_block?(block_ast)
65
+
66
+ case block_ast.children[0].type
67
+ when :CALL # RSpec.describe "something" do end
68
+ block_ast.children[0].children[2].children[0]
69
+ when :FCALL # describe "something" do end
70
+ block_ast.children[0].children[1].children[0]
71
+ end
72
+ end
73
+
74
+ # @param block_ast [RubyVM::AbstractSyntaxTree::Node]
75
+ # @return [String]
76
+ def self.let_method_name(block_ast)
77
+ block_ast.children[0].children[1]&.children&.[](0)&.children&.[](0)&.to_s
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Rspec
5
+ class SpecWalker
6
+ class RspecContextNamespace
7
+ class << self
8
+ # @param block_ast [RubyVM::AbstractSyntaxTree::Node]
9
+ # @return [String, nil]
10
+ def from_block_ast(block_ast)
11
+ return unless block_ast.is_a?(RubyVM::AbstractSyntaxTree::Node)
12
+
13
+ ast = NodeTypes.context_description_node(block_ast)
14
+ if ast.type == :STR
15
+ string_to_const_name(ast)
16
+ elsif NodeTypes.a_constant?(ast)
17
+ FullConstantName.from_ast(ast).gsub('::', '')
18
+ else
19
+ Solargraph.logger.warn "[RSpec] Unexpected AST type #{ast.type}"
20
+ nil
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ # @see https://github.com/rspec/rspec-core/blob/1eeadce5aa7137ead054783c31ff35cbfe9d07cc/lib/rspec/core/example_group.rb#L862
27
+ # @param ast [Parser::AST::Node]
28
+ # @return [String]
29
+ def string_to_const_name(string_ast)
30
+ return unless string_ast.type == :STR
31
+
32
+ name = string_ast.children[0]
33
+ return 'Anonymous'.dup if name.empty?
34
+
35
+ # Convert to CamelCase.
36
+ name = +" #{name}"
37
+ name.gsub!(/[^0-9a-zA-Z]+([0-9a-zA-Z])/) do
38
+ match = ::Regexp.last_match[1]
39
+ match.upcase!
40
+ match
41
+ end
42
+
43
+ name.lstrip! # Remove leading whitespace
44
+ name.gsub!(/\W/, '') # JRuby, RBX and others don't like non-ascii in const names
45
+
46
+ # Ruby requires first const letter to be A-Z. Use `Nested`
47
+ # as necessary to enforce that.
48
+ name.gsub!(/\A([^A-Z]|\z)/, 'Nested\1')
49
+
50
+ name
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -1,6 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'walker'
4
+ require_relative 'spec_walker/node_types'
5
+ require_relative 'spec_walker/full_constant_name'
6
+ require_relative 'spec_walker/rspec_context_namespace'
7
+ require_relative 'spec_walker/fake_let_method'
4
8
 
5
9
  module Solargraph
6
10
  module Rspec
@@ -10,7 +14,7 @@ module Solargraph
10
14
  def initialize(source_map:, config:)
11
15
  @source_map = source_map
12
16
  @config = config
13
- @walker = Rspec::Walker.from_source(source_map.source)
17
+ @walker = Rspec::Walker.new(source_map.source.node)
14
18
  @handlers = {
15
19
  on_described_class: [],
16
20
  on_let_method: [],
@@ -30,24 +34,34 @@ module Solargraph
30
34
  attr_reader :config
31
35
 
32
36
  # @param block [Proc]
37
+ # @yieldparam class_name [String]
38
+ # @yieldparam location_range [Solargraph::Range]
33
39
  # @return [void]
34
40
  def on_described_class(&block)
35
41
  @handlers[:on_described_class] << block
36
42
  end
37
43
 
38
44
  # @param block [Proc]
45
+ # @yieldparam method_name [String]
46
+ # @yieldparam location_range [Solargraph::Range]
47
+ # @yieldparam fake_method_ast [RubyVM::AbstractSyntaxTree::Node]
39
48
  # @return [void]
40
49
  def on_let_method(&block)
41
50
  @handlers[:on_let_method] << block
42
51
  end
43
52
 
44
53
  # @param block [Proc]
54
+ # @yieldparam method_name [String]
55
+ # @yieldparam location_range [Solargraph::Range]
56
+ # @yieldparam fake_method_ast [RubyVM::AbstractSyntaxTree::Node]
45
57
  # @return [void]
46
58
  def on_subject(&block)
47
59
  @handlers[:on_subject] << block
48
60
  end
49
61
 
50
62
  # @param block [Proc]
63
+ # @yieldparam namespace_name [String]
64
+ # @yieldparam location_range [Solargraph::Range]
51
65
  # @return [void]
52
66
  def on_each_context_block(&block)
53
67
  @handlers[:on_each_context_block] << block
@@ -55,18 +69,21 @@ module Solargraph
55
69
 
56
70
  #
57
71
  # @param block [Proc]
72
+ # @yieldparam location_range [Solargraph::Range]
58
73
  # @return [void]
59
74
  def on_example_block(&block)
60
75
  @handlers[:on_example_block] << block
61
76
  end
62
77
 
63
78
  # @param block [Proc]
79
+ # @yieldparam location_range [Solargraph::Range]
64
80
  # @return [void]
65
81
  def on_hook_block(&block)
66
82
  @handlers[:on_hook_block] << block
67
83
  end
68
84
 
69
85
  # @param block [Proc]
86
+ # @yieldparam location_range [Solargraph::Range]
70
87
  # @return [void]
71
88
  def on_blocks_in_examples(&block)
72
89
  @handlers[:on_blocks_in_examples] << block
@@ -80,71 +97,72 @@ module Solargraph
80
97
 
81
98
  # @return [void]
82
99
  def walk!
83
- each_context_block(@walker.ast, Rspec::ROOT_NAMESPACE) do |namespace_name, ast|
100
+ each_context_block(@walker.ast, Rspec::ROOT_NAMESPACE) do |namespace_name, block_ast|
101
+ desc_node = NodeTypes.context_description_node(block_ast)
102
+
84
103
  @handlers[:on_each_context_block].each do |handler|
85
- handler.call(namespace_name, ast)
104
+ handler.call(namespace_name, PinFactory.build_location_range(block_ast))
86
105
  end
87
- end
88
106
 
89
- rspec_const = ::Parser::AST::Node.new(:const, [nil, :RSpec])
90
- walker.on :send, [rspec_const, :describe, :any] do |ast|
91
- @handlers[:on_described_class].each do |handler|
92
- class_ast = ast.children[2]
93
- next unless class_ast
94
-
95
- class_name = full_constant_name(class_ast)
96
- handler.call(class_ast, class_name)
107
+ if NodeTypes.a_constant?(desc_node) # rubocop:disable Style/Next
108
+ @handlers[:on_described_class].each do |handler|
109
+ class_name_ast = NodeTypes.context_description_node(block_ast)
110
+ class_name = FullConstantName.from_ast(class_name_ast)
111
+ handler.call(class_name, PinFactory.build_location_range(class_name_ast))
112
+ end
97
113
  end
98
114
  end
99
115
 
100
- config.let_methods.each do |let_method|
101
- walker.on :send, [nil, let_method] do |ast|
102
- @handlers[:on_let_method].each do |handler|
103
- handler.call(ast)
104
- end
116
+ walker.on :ITER do |block_ast|
117
+ next unless NodeTypes.a_let_block?(block_ast, config)
118
+
119
+ method_name = NodeTypes.let_method_name(block_ast)
120
+ next unless method_name
121
+
122
+ fake_method_ast = FakeLetMethod.transform_block(block_ast, @source_map.source.code)
123
+
124
+ @handlers[:on_let_method].each do |handler|
125
+ handler.call(method_name, PinFactory.build_location_range(block_ast.children[0]), fake_method_ast)
105
126
  end
106
127
  end
107
128
 
108
- walker.on :send, [nil, :subject] do |ast|
129
+ walker.on :ITER do |block_ast|
130
+ next unless NodeTypes.a_subject_block?(block_ast)
131
+
132
+ method_name = NodeTypes.let_method_name(block_ast)
133
+ fake_method_ast = FakeLetMethod.transform_block(block_ast, @source_map.source.code, method_name || 'subject')
134
+
109
135
  @handlers[:on_subject].each do |handler|
110
- handler.call(ast)
136
+ handler.call(method_name, PinFactory.build_location_range(block_ast.children[0]), fake_method_ast)
111
137
  end
112
138
  end
113
139
 
114
- walker.on :block do |block_ast|
115
- next if block_ast.children.first.type != :send
116
-
117
- method_ast = block_ast.children.first
118
- method_name = method_ast.children[1]
119
- next unless Rspec::EXAMPLE_METHODS.include?(method_name.to_s)
140
+ walker.on :ITER do |block_ast|
141
+ next unless NodeTypes.a_example_block?(block_ast)
120
142
 
121
143
  @handlers[:on_example_block].each do |handler|
122
- handler.call(block_ast)
144
+ handler.call(PinFactory.build_location_range(block_ast))
123
145
  end
124
146
 
125
- # @param blocks_in_examples [Parser::AST::Node]
126
- each_block(block_ast.children[2]) do |blocks_in_examples|
147
+ # @param blocks_in_examples [RubyVM::AbstractSyntaxTree::Node]
148
+ each_block(block_ast.children[1]) do |blocks_in_examples|
127
149
  @handlers[:on_blocks_in_examples].each do |handler|
128
- handler.call(blocks_in_examples)
150
+ handler.call(PinFactory.build_location_range(blocks_in_examples))
129
151
  end
130
152
  end
131
153
  end
132
154
 
133
- walker.on :block do |block_ast|
134
- next if block_ast.children.first.type != :send
135
-
136
- method_ast = block_ast.children.first
137
- method_name = method_ast.children[1]
138
- next unless Rspec::HOOK_METHODS.include?(method_name.to_s)
155
+ walker.on :ITER do |block_ast|
156
+ next unless NodeTypes.a_hook_block?(block_ast)
139
157
 
140
158
  @handlers[:on_hook_block].each do |handler|
141
- handler.call(block_ast)
159
+ handler.call(PinFactory.build_location_range(block_ast))
142
160
  end
143
161
 
144
- # @param blocks_in_examples [Parser::AST::Node]
145
- each_block(block_ast.children[2]) do |blocks_in_examples|
162
+ # @param blocks_in_examples [RubyVM::AbstractSyntaxTree::Node]
163
+ each_block(block_ast.children[1]) do |blocks_in_examples|
146
164
  @handlers[:on_blocks_in_examples].each do |handler|
147
- handler.call(blocks_in_examples)
165
+ handler.call(PinFactory.build_location_range(blocks_in_examples))
148
166
  end
149
167
  end
150
168
  end
@@ -159,9 +177,9 @@ module Solargraph
159
177
  # @param ast [Parser::AST::Node]
160
178
  # @param parent_result [Object]
161
179
  def each_block(ast, parent_result = nil, &block)
162
- return unless ast.is_a?(::Parser::AST::Node)
180
+ return unless ast.is_a?(RubyVM::AbstractSyntaxTree::Node)
163
181
 
164
- is_a_block = ast.type == :block && ast.children[0].type == :send
182
+ is_a_block = NodeTypes.a_block?(ast)
165
183
 
166
184
  if is_a_block
167
185
  result = block&.call(ast, parent_result)
@@ -176,12 +194,11 @@ module Solargraph
176
194
  # @yield [String, Parser::AST::Node]
177
195
  def each_context_block(ast, root_namespace = Rspec::ROOT_NAMESPACE, &block)
178
196
  each_block(ast, root_namespace) do |block_ast, parent_namespace|
179
- is_a_context = %i[describe context].include?(block_ast.children[0].children[1])
197
+ is_a_context = NodeTypes.a_context_block?(block_ast)
180
198
 
181
199
  next unless is_a_context
182
200
 
183
- description_node = block_ast.children[0].children[2]
184
- block_name = rspec_describe_class_name(description_node)
201
+ block_name = RspecContextNamespace.from_block_ast(block_ast)
185
202
  next unless block_name
186
203
 
187
204
  parent_namespace = namespace_name = "#{parent_namespace}::#{block_name}"
@@ -189,59 +206,6 @@ module Solargraph
189
206
  next parent_namespace
190
207
  end
191
208
  end
192
-
193
- # @param ast [Parser::AST::Node]
194
- # @return [String, nil]
195
- def rspec_describe_class_name(ast)
196
- if ast.type == :str
197
- string_to_const_name(ast)
198
- elsif ast.type == :const
199
- full_constant_name(ast).gsub('::', '')
200
- else
201
- Solargraph.logger.warn "[RSpec] Unexpected AST type #{ast.type}"
202
- nil
203
- end
204
- end
205
-
206
- # @param ast [Parser::AST::Node]
207
- # @return [String]
208
- def full_constant_name(ast)
209
- raise 'Node is not a constant' unless ast.type == :const
210
-
211
- name = ast.children[1].to_s
212
- if ast.children[0].nil?
213
- name
214
- else
215
- "#{full_constant_name(ast.children[0])}::#{name}"
216
- end
217
- end
218
-
219
- # @see https://github.com/rspec/rspec-core/blob/1eeadce5aa7137ead054783c31ff35cbfe9d07cc/lib/rspec/core/example_group.rb#L862
220
- # @param ast [Parser::AST::Node]
221
- # @return [String]
222
- def string_to_const_name(string_ast)
223
- return unless string_ast.type == :str
224
-
225
- name = string_ast.children[0]
226
- return 'Anonymous'.dup if name.empty?
227
-
228
- # Convert to CamelCase.
229
- name = +" #{name}"
230
- name.gsub!(/[^0-9a-zA-Z]+([0-9a-zA-Z])/) do
231
- match = ::Regexp.last_match[1]
232
- match.upcase!
233
- match
234
- end
235
-
236
- name.lstrip! # Remove leading whitespace
237
- name.gsub!(/\W/, '') # JRuby, RBX and others don't like non-ascii in const names
238
-
239
- # Ruby requires first const letter to be A-Z. Use `Nested`
240
- # as necessary to enforce that.
241
- name.gsub!(/\A([^A-Z]|\z)/, 'Nested\1')
242
-
243
- name
244
- end
245
209
  end
246
210
  end
247
211
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Solargraph
4
4
  module Rspec
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
6
6
  end
7
7
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Credits: This file is a copy of the original file from the solargraph-rails gem.
4
-
5
3
  module Solargraph
6
4
  module Rspec
7
5
  class Walker
6
+ class ParsingError < StandardError; end
7
+
8
8
  class Hook
9
9
  attr_reader :node_type
10
10
 
@@ -17,7 +17,7 @@ module Solargraph
17
17
  @proc = Proc.new(&block)
18
18
  end
19
19
 
20
- # @param node [Parser::AST::Node]
20
+ # @param node [RubyVM::AbstractSyntaxTree::Node]
21
21
  # @return [void]
22
22
  def visit(node)
23
23
  return unless matches?(node)
@@ -33,15 +33,15 @@ module Solargraph
33
33
 
34
34
  private
35
35
 
36
- # @param node [Parser::AST::Node]
36
+ # @param node [RubyVM::AbstractSyntaxTree::Node]
37
37
  # @return [Boolean]
38
38
  def matches?(node)
39
39
  return false unless node.type == node_type
40
40
  return false unless node.children
41
41
  return true if @args.empty?
42
42
 
43
- a_child_matches = node.children.first.is_a?(::Parser::AST::Node) && node.children.any? do |child|
44
- child.is_a?(::Parser::AST::Node) &&
43
+ a_child_matches = node.children.first.is_a?(RubyVM::AbstractSyntaxTree::Node) && node.children.any? do |child|
44
+ child.is_a?(RubyVM::AbstractSyntaxTree::Node) &&
45
45
  match_children(child.children, @args[1..])
46
46
  end
47
47
 
@@ -50,12 +50,12 @@ module Solargraph
50
50
  match_children(node.children)
51
51
  end
52
52
 
53
- # @param children [Array<Parser::AST::Node>]
53
+ # @param children [Array<RubyVM::AbstractSyntaxTree::Node>]
54
54
  def match_children(children, args = @args)
55
55
  args.each_with_index.all? do |arg, i|
56
56
  if arg == :any
57
57
  true
58
- elsif children[i].is_a?(::Parser::AST::Node) && arg.is_a?(Symbol)
58
+ elsif children[i].is_a?(RubyVM::AbstractSyntaxTree::Node) && arg.is_a?(Symbol)
59
59
  children[i].type == arg
60
60
  else
61
61
  children[i] == arg
@@ -64,28 +64,9 @@ module Solargraph
64
64
  end
65
65
  end
66
66
 
67
- # https://github.com/castwide/solargraph/issues/522
68
- def self.normalize_ast(source)
69
- ast = source.node
70
-
71
- if ast.is_a?(::Parser::AST::Node)
72
- ast
73
- else
74
- NodeParser.parse_with_comments(source.code, source.filename)
75
- end
76
- end
77
-
78
- # @param source [Solargraph::Source]
79
- def self.from_source(source)
80
- new(*normalize_ast(source))
81
- end
82
-
83
- # @return ast [Parser::AST::Node]
84
- attr_reader :ast
85
- # @return comments [Hash]
86
- attr_reader :comments
67
+ attr_reader :ast, :comments
87
68
 
88
- # @param ast [Parser::AST::Node]
69
+ # @param ast [RubyVM::AbstractSyntaxTree::Node]
89
70
  # @param comments [Hash]
90
71
  def initialize(ast, comments = {})
91
72
  @comments = comments
@@ -93,23 +74,18 @@ module Solargraph
93
74
  @hooks = Hash.new([])
94
75
  end
95
76
 
96
- # @param node_type [Symbol]
97
- # @param args [Array]
98
- # @param block [Proc]
99
77
  def on(node_type, args = [], &block)
100
78
  @hooks[node_type] << Hook.new(node_type, args, &block)
101
79
  end
102
80
 
103
- # @return [void]
104
81
  def walk
105
82
  @ast.is_a?(Array) ? @ast.each { |node| traverse(node) } : traverse(@ast)
106
83
  end
107
84
 
108
85
  private
109
86
 
110
- # @param node [Parser::AST::Node]
111
87
  def traverse(node)
112
- return unless node.is_a?(::Parser::AST::Node)
88
+ return unless node.is_a?(RubyVM::AbstractSyntaxTree::Node)
113
89
 
114
90
  @hooks[node.type].each { |hook| hook.visit(node) }
115
91
 
@@ -2,7 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'solargraph'
5
- require 'active_support'
6
5
 
7
6
  require_relative 'solargraph/rspec/version'
8
7
  require_relative 'solargraph/rspec/convention'
@@ -28,7 +28,6 @@ Gem::Specification.new do |spec|
28
28
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
29
  spec.require_paths = ['lib']
30
30
 
31
- spec.add_runtime_dependency 'activesupport', '~> 6.0'
32
31
  spec.add_runtime_dependency 'solargraph', '~> 0.49', '>= 0.49.0'
33
32
 
34
33
  # For more information and examples about making a new gem, check out our
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph-rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
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-05-11 00:00:00.000000000 Z
11
+ date: 2024-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: activesupport
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '6.0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '6.0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: solargraph
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -72,8 +58,12 @@ files:
72
58
  - lib/solargraph/rspec/correctors/let_methods_corrector.rb
73
59
  - lib/solargraph/rspec/correctors/subject_method_corrector.rb
74
60
  - lib/solargraph/rspec/correctors/walker_base.rb
61
+ - lib/solargraph/rspec/pin_factory.rb
75
62
  - lib/solargraph/rspec/spec_walker.rb
76
- - lib/solargraph/rspec/util.rb
63
+ - lib/solargraph/rspec/spec_walker/fake_let_method.rb
64
+ - lib/solargraph/rspec/spec_walker/full_constant_name.rb
65
+ - lib/solargraph/rspec/spec_walker/node_types.rb
66
+ - lib/solargraph/rspec/spec_walker/rspec_context_namespace.rb
77
67
  - lib/solargraph/rspec/version.rb
78
68
  - lib/solargraph/rspec/walker.rb
79
69
  - lib/solargraph_rspec.rb
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Credits: This file is a copy of the file from the solargraph-rspec gem
4
-
5
- # rubocop:disable Naming/MethodParameterName
6
- module Solargraph
7
- module Rspec
8
- # Utility methods for building pins and references.
9
- module Util
10
- def self.build_public_method(
11
- ns,
12
- name,
13
- types: nil,
14
- location: nil,
15
- comments: [],
16
- attribute: false,
17
- scope: :instance
18
- )
19
- opts = {
20
- name: name,
21
- location: location,
22
- closure: ns,
23
- scope: scope,
24
- attribute: attribute,
25
- comments: []
26
- }
27
-
28
- comments << "@return [#{types.join(",")}]" if types
29
-
30
- opts[:comments] = comments.join("\n")
31
-
32
- Solargraph::Pin::Method.new(**opts)
33
- end
34
-
35
- def self.build_module_include(ns, module_name, location)
36
- Solargraph::Pin::Reference::Include.new(
37
- closure: ns,
38
- name: module_name,
39
- location: location
40
- )
41
- end
42
-
43
- def self.build_module_extend(ns, module_name, location)
44
- Solargraph::Pin::Reference::Extend.new(
45
- closure: ns,
46
- name: module_name,
47
- location: location
48
- )
49
- end
50
-
51
- def self.dummy_location(path)
52
- Solargraph::Location.new(
53
- File.expand_path(path),
54
- Solargraph::Range.from_to(0, 0, 0, 0)
55
- )
56
- end
57
-
58
- # @param ast [Parser::AST::Node]
59
- def self.build_location(ast, path)
60
- Solargraph::Location.new(
61
- File.expand_path(path),
62
- Solargraph::Range.from_to(
63
- ast.location.first_line,
64
- ast.location.column,
65
- ast.location.last_line,
66
- ast.location.last_column
67
- )
68
- )
69
- end
70
-
71
- def self.method_return(path, type)
72
- Solargraph::Pin::Reference::Override.method_return(path, type)
73
- end
74
- end
75
- end
76
- end
77
- # rubocop:enable Naming/MethodParameterName