rubocop-fourshark 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d37d6aedd6756dcc500a7295b9f03dd99f413d12375c29826d5ac6970e11aacc
4
- data.tar.gz: 7e406a1cb9ddde1f494a3e6d1c90561c87b6bf2d19cc585d69c25c43516a39ea
3
+ metadata.gz: ff1f92dab1c4c499529e7729afcfe28e449879582f476e2a911952ec3140f8df
4
+ data.tar.gz: 17f2ab8e91dd9392f74bc0cf333dcf58b54b847e67bd05224ad4394857b583b8
5
5
  SHA512:
6
- metadata.gz: ac6cbcbeaa39f99a6e548b93a7ad05c2cc204013210dbb50686252c3e0c7285d419daf306d53aedc00080d295b7c61efd016f59276e48a0519391e427e287e5c
7
- data.tar.gz: 540e6ea1264bcf27eeb261546ab74bd75c165bb19488e7098dd358d303e10e162d120c3ef0ea5b3698077bb03cc3a18e59af2ae7f009f24020463ebc3956d8e2
6
+ metadata.gz: ad46dc84d1c4930addcb691f17b405685d684eaaa2fe12eb45353ce366ad352e9bc2c79ed65bc9e5b8da4c94579bebcaba65e1170ac809df467dde62d69c8196
7
+ data.tar.gz: f7a40f52df08988e967789e44bd7d74271a9074e14819bfc3e3c315afb7b07a6c0fdc9bba256a021b579c480158956aec9ef5066ba05c5210463d0c53fd1695d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## [0.11.2] - 2026-10-07
2
+
3
+ ### Added
4
+
5
+ - `Layout/SingleLineStatementSpacing` coverage for RSpec cops that forbid consecutive one-liners
6
+
7
+ ### Fixed
8
+
9
+ - `Layout/SingleLineStatementSpacing` — the blank line after a module inclusion or attribute accessor run is no longer removed
10
+
11
+ ## [0.11.1] - 2026-10-07
12
+
13
+ ### Fixed
14
+
15
+ - `Layout/SingleLineStatementSpacing` — the blank line after a `let`, `subject`, hook or example run is no longer removed
16
+ - `Layout/SingleLineStatementSpacing` — the blank line between two gem sections is no longer removed
17
+ - `Layout/SingleLineStatementSpacing` — the blank line after a hook or example written with a numbered or `it` block parameter is no longer removed
18
+ - `Layout/SingleLineStatementSpacing` — the blank line between two subjects or after a one-line example group is no longer removed
19
+ - `Layout/SingleLineStatementSpacing` — consecutive one-line hooks and examples are joined only while their RSpec cop allows it
20
+
1
21
  ## [0.11.0] - 2026-10-07
2
22
 
3
23
  ### Changed
@@ -8,7 +8,9 @@ module RuboCop
8
8
  # Forbids a blank line between two consecutive single-line statements —
9
9
  # they are one run, so the blank reveals nothing. A blank that separates
10
10
  # code from an adjacent comment is kept, as is one owned by another cop
11
- # (a guard clause, a flow-control statement, an access modifier) or one
11
+ # (a guard clause, a flow-control statement, an access modifier, the end
12
+ # of an RSpec `let`/`subject`/hook/example run, the end of a module
13
+ # inclusion or attribute accessor run, a Bundler gem section) or one
12
14
  # beside a multi-line or heredoc neighbour. Autocorrects by removing it.
13
15
  class SingleLineStatementSpacing < ::RuboCop::Cop::Base
14
16
  extend ::RuboCop::Cop::AutoCorrector
@@ -16,11 +18,67 @@ module RuboCop
16
18
  FLOW_CONTROL_METHODS = %i[raise fail throw].freeze
17
19
  FLOW_CONTROL_TYPES = %i[return next break redo retry].freeze
18
20
  MSG = 'Remove the blank line between consecutive single-line statements.'
21
+ ONE_LINER_RUN_COPS = { example: 'RSpec/EmptyLineAfterExample', hook: 'RSpec/EmptyLineAfterHook' }.freeze
22
+
23
+ RSPEC_KINDS = {
24
+ after: :hook,
25
+ append_after: :hook,
26
+ append_before: :hook,
27
+ around: :hook,
28
+ before: :hook,
29
+ context: :example_group,
30
+ describe: :example_group,
31
+ example: :example,
32
+ example_group: :example_group,
33
+ fcontext: :example_group,
34
+ fdescribe: :example_group,
35
+ feature: :example_group,
36
+ fexample: :example,
37
+ ffeature: :example_group,
38
+ fit: :example,
39
+ focus: :example,
40
+ fscenario: :example,
41
+ fspecify: :example,
42
+ it: :example,
43
+ its: :example,
44
+ let: :let,
45
+ let!: :let,
46
+ pending: :example,
47
+ prepend_after: :hook,
48
+ prepend_before: :hook,
49
+ scenario: :example,
50
+ shared_context: :example_group,
51
+ shared_examples: :example_group,
52
+ shared_examples_for: :example_group,
53
+ skip: :example,
54
+ specify: :example,
55
+ subject: :subject,
56
+ subject!: :subject,
57
+ xcontext: :example_group,
58
+ xdescribe: :example_group,
59
+ xexample: :example,
60
+ xfeature: :example_group,
61
+ xit: :example,
62
+ xscenario: :example,
63
+ xspecify: :example
64
+ }.freeze
65
+
66
+ STATEMENT_RUN_KINDS = {
67
+ attr: :attribute_accessor,
68
+ attr_accessor: :attribute_accessor,
69
+ attr_reader: :attribute_accessor,
70
+ attr_writer: :attribute_accessor,
71
+ extend: :module_inclusion,
72
+ include: :module_inclusion,
73
+ prepend: :module_inclusion
74
+ }.freeze
19
75
 
20
76
  def on_begin(node)
21
77
  node.children.each_cons(2) do |first, second|
22
78
  next unless first.is_a?(::RuboCop::AST::Node) && second.is_a?(::RuboCop::AST::Node)
23
79
  next if structural?(first) || structural?(second)
80
+ next if rspec_run_ends?(first, second) || statement_run_ends?(first, second)
81
+ next if gem_section_boundary?(first, second)
24
82
 
25
83
  blanks = removable_blank_lines(first, second)
26
84
 
@@ -64,6 +122,67 @@ module RuboCop
64
122
  node.send_type? && node.receiver.nil? && ACCESS_MODIFIERS.include?(node.method_name)
65
123
  end
66
124
 
125
+ # The `RSpec/EmptyLineAfter*` cops demand a blank after the last `let`,
126
+ # `subject`, hook, example or example group of a run; removing it makes the two cops fight.
127
+ def rspec_run_ends?(first, second)
128
+ kind = rspec_kind(first)
129
+
130
+ return false if kind.nil?
131
+ return true if kind != rspec_kind(second)
132
+
133
+ !one_liner_run_allowed?(kind)
134
+ end
135
+
136
+ # Only `let`s always run together; hooks and examples do while their cop keeps
137
+ # `AllowConsecutiveOneLiners`, and subjects and example groups never do.
138
+ def one_liner_run_allowed?(kind)
139
+ return true if kind == :let
140
+
141
+ cop_name = ONE_LINER_RUN_COPS[kind]
142
+
143
+ return false if cop_name.nil?
144
+
145
+ config.for_cop(cop_name).fetch('AllowConsecutiveOneLiners', true)
146
+ end
147
+
148
+ def rspec_kind(node)
149
+ call =
150
+ if node.any_block_type?
151
+ node.send_node
152
+ else
153
+ node
154
+ end
155
+
156
+ return nil if !call.send_type? || call.receiver
157
+
158
+ RSPEC_KINDS[call.method_name]
159
+ end
160
+
161
+ # `Layout/EmptyLinesAfterModuleInclusion` and `Layout/EmptyLinesAroundAttributeAccessor`
162
+ # demand a blank after the last `include`/`extend`/`prepend` or `attr_*` of a run.
163
+ def statement_run_ends?(first, second)
164
+ kind = statement_run_kind(first)
165
+
166
+ return false if kind.nil?
167
+
168
+ kind != statement_run_kind(second)
169
+ end
170
+
171
+ def statement_run_kind(node)
172
+ return nil if !node.send_type? || node.receiver
173
+
174
+ STATEMENT_RUN_KINDS[node.method_name]
175
+ end
176
+
177
+ # `Bundler/OrderedGems` reads a blank between two `gem` lines as a section break.
178
+ def gem_section_boundary?(first, second)
179
+ gem_declaration?(first) && gem_declaration?(second)
180
+ end
181
+
182
+ def gem_declaration?(node)
183
+ node.send_type? && node.receiver.nil? && node.method?(:gem)
184
+ end
185
+
67
186
  # A blank whose nearest non-blank line on each side is the same kind
68
187
  # (code-to-code or comment-to-comment). A blank on a code/comment border
69
188
  # separates the two deliberately and is left alone.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Fourshark
5
- VERSION = '0.11.0'
5
+ VERSION = '0.11.2'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-fourshark
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.11.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paulo Ribeiro