yoshiki 11.0.0.pre.12 → 11.0.0.pre.13

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: 7880f8dd34e18f32da07f286fdabfecfad92b70f420a0cc11f4a69768b84980d
4
- data.tar.gz: 6a11267e9a64df75b2708935076400fdb6898ef5872a262ec04edc9ae0971dc8
3
+ metadata.gz: 35fa2afafcdcf1908eb5090d37ab33868394bc5bd449e14bcb24015d4bedb038
4
+ data.tar.gz: e70d04d068aa8805eb5c01cad47cfa7225d93d7b9a2a1e9828ee24ed11ccb5e3
5
5
  SHA512:
6
- metadata.gz: d458f79d7411fc843cf6bd3518f02a251b1d27a4492323739fd430358391b93fc8d04f00103e7068f00016cea41ff3486db707b5c19ece209872485f9f70d7d8
7
- data.tar.gz: 328635ca21159c25ed41674d1aac844495168d4ba19306cc28d264d981d292594e578a87d6f037380893d519a21cebf01d2515bf540e8a48353ce41adbe7f438
6
+ metadata.gz: 9737edb1d4b3c105116cdfe2e94fecca8e4f201fb8604db9044e518181dff395f0d518261b6e45dcb5c3d97e44e4b51037c80f3ed06fa6dd032d1b501a2320d8
7
+ data.tar.gz: 4c37de5c3f6523515590690317d2c32d7427ea5717a02ff69ed682022658976d512da303da5a754f15a9d9f795120d17a761f92061c2f89ebad9e82c07b9a773
data/.yoshiki-ruby.yml CHANGED
@@ -185,6 +185,12 @@ Style/TrailingUnderscoreVariable:
185
185
 
186
186
  Yoshiki/Layout/EmptyLineBeforeComment:
187
187
  Enabled: true
188
+ Yoshiki/Layout/EmptyLineAroundMultilineAssignment:
189
+ Enabled: true
190
+ Yoshiki/Layout/EmptyLineAroundMultilineBlock:
191
+ Enabled: true
192
+ Yoshiki/Layout/EmptyLineAroundMultilineConditional:
193
+ Enabled: true
188
194
  Yoshiki/Layout/HangingKeywordArguments:
189
195
  Enabled: true
190
196
  MinKeywords: 2
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- yoshiki (11.0.0.pre.12)
4
+ yoshiki (11.0.0.pre.13)
5
5
  rubocop (= 1.89.0)
6
6
  rubocop-performance (= 1.26.1)
7
7
  rubocop-rake (= 0.7.1)
@@ -0,0 +1,81 @@
1
+ module RuboCop
2
+ module Cop
3
+ module Yoshiki
4
+ module EmptyLineAroundMultilineStatement
5
+ # Classifies begin-sequence statements that should be their own paragraph.
6
+ module Paragraph
7
+
8
+ BLOCK_TYPES = %i[block numblock itblock].freeze
9
+ CONDITIONAL_TYPES = %i[if case case_match while until for kwbegin].freeze
10
+ BODY_TYPES = (BLOCK_TYPES + CONDITIONAL_TYPES).freeze
11
+
12
+ private
13
+
14
+ def statement_in_sequence? node
15
+ parent = node.parent
16
+ parent&.begin_type? || parent&.kwbegin_type?
17
+ end
18
+
19
+ def paragraph_statement? node
20
+ statement_in_sequence?(node) && (
21
+ assignment_paragraph?(node) ||
22
+ block_paragraph?(node) ||
23
+ conditional_paragraph?(node)
24
+ )
25
+ end
26
+
27
+ def assignment_paragraph? node
28
+ rhs = assignment_rhs(node)
29
+ rhs && bodyish?(rhs)
30
+ end
31
+
32
+ def block_paragraph? node
33
+ BLOCK_TYPES.include?(node.type) && node.multiline?
34
+ end
35
+
36
+ def conditional_paragraph? node
37
+ return false unless CONDITIONAL_TYPES.include?(node.type)
38
+ return false if skip_form?(node)
39
+
40
+ node.multiline?
41
+ end
42
+
43
+ def assignment_rhs node
44
+ if node.call_type?
45
+ return unless node.assignment_method? && node.loc.operator
46
+
47
+ node.last_argument
48
+ elsif node.assignment?
49
+ node.expression
50
+ end
51
+ end
52
+
53
+ def bodyish? node
54
+ return true if heredoc?(node)
55
+ return false unless BODY_TYPES.include?(node.type)
56
+ return false if skip_form?(node)
57
+
58
+ node.multiline?
59
+ end
60
+
61
+ def skip_form? node
62
+ return true if node.if_type? && node.ternary?
63
+ return true if node.respond_to?(:modifier_form?) && node.modifier_form?
64
+
65
+ false
66
+ end
67
+
68
+ def heredoc? node
69
+ node.each_node.any? { heredoc_end_line(it) }
70
+ end
71
+
72
+ def heredoc_end_line node
73
+ loc = node.loc
74
+ loc.heredoc_end.line if loc.respond_to?(:heredoc_end) && loc.heredoc_end
75
+ end
76
+
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,94 @@
1
+ require_relative 'empty_line_around_multiline_statement/paragraph'
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Yoshiki
6
+ # Shared "paragraph" isolation for multiline assignment / block /
7
+ # conditional statements that sit next to siblings.
8
+ #
9
+ # ExtraSpacing owns `=` padding. After a blank splits an alignment
10
+ # group, ForceEqualSignAlignment stops stretching neighbors.
11
+ module EmptyLineAroundMultilineStatement
12
+
13
+ include RangeHelp
14
+ include Paragraph
15
+
16
+ private
17
+
18
+ def check_empty_lines_around node
19
+ return unless statement_in_sequence?(node)
20
+
21
+ check_blank_before(node)
22
+ check_blank_after(node)
23
+ end
24
+
25
+ def check_blank_before node
26
+ return unless node.left_sibling
27
+ return if glued_to_left_sibling?(node)
28
+ return if blank_line?(node.first_line - 1)
29
+ return if processed_source.comment_at_line(node.first_line - 1)
30
+
31
+ add_offense(before_range(node), message: self.class::MSG_BEFORE) do |corrector|
32
+ corrector.insert_before(line_begin(node.first_line), "\n")
33
+ end
34
+ end
35
+
36
+ def check_blank_after node
37
+ sibling = node.right_sibling
38
+ return unless sibling
39
+ return if paragraph_statement?(sibling)
40
+ return if glued_to_right_sibling?(node, sibling)
41
+
42
+ last = last_physical_line(node)
43
+ return if blank_line?(last + 1)
44
+ return if processed_source.comment_at_line(last + 1)
45
+
46
+ add_offense(after_range(node), message: self.class::MSG_AFTER) do |corrector|
47
+ corrector.insert_after(whole_line(last), "\n")
48
+ end
49
+ end
50
+
51
+ def glued_to_left_sibling? node
52
+ last_physical_line(node.left_sibling) == node.first_line
53
+ end
54
+
55
+ def glued_to_right_sibling? node, sibling
56
+ last_physical_line(node) == sibling.first_line
57
+ end
58
+
59
+ def last_physical_line node
60
+ ends = node.each_node.filter_map { heredoc_end_line(it) }
61
+ [ node.last_line, *ends ].max
62
+ end
63
+
64
+ def blank_line? lineno
65
+ return true if lineno < 1
66
+
67
+ line = processed_source.lines[lineno - 1]
68
+ line.nil? || line.strip.empty?
69
+ end
70
+
71
+ def before_range node
72
+ node.source_range.begin
73
+ end
74
+
75
+ def after_range node
76
+ loc = node.loc
77
+ last = last_physical_line(node)
78
+ return loc.end if loc.respond_to?(:end) && loc.end && loc.end.line == last
79
+
80
+ whole_line(last)
81
+ end
82
+
83
+ def line_begin lineno
84
+ source_range(processed_source.buffer, lineno, 0)
85
+ end
86
+
87
+ def whole_line lineno
88
+ range_by_whole_lines(line_begin(lineno))
89
+ end
90
+
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,72 @@
1
+ module RuboCop
2
+ module Cop
3
+ module Yoshiki
4
+ module Layout
5
+ # Isolates a multiline assignment from neighboring statements with a
6
+ # blank line. "Multiline" here means the RHS is a body (block, heredoc,
7
+ # `if` / `case` / `begin`, …), not a hanging call or array/hash wrap.
8
+ #
9
+ # Setter sends (`spec.description =`) count. A `do`/`end` that is the
10
+ # whole statement (not assigned) is Yoshiki/Layout/EmptyLineAroundMultilineBlock.
11
+ # A sibling `if`/`case` is Yoshiki/Layout/EmptyLineAroundMultilineConditional.
12
+ #
13
+ # Layout/ExtraSpacing (ForceEqualSignAlignment) pads `=` in a group;
14
+ # a blank line splits that group.
15
+ #
16
+ # @example
17
+ # # bad
18
+ # spec.summary = 'short'
19
+ # spec.description = <<~DESC
20
+ # long
21
+ # DESC
22
+ #
23
+ # # good
24
+ # spec.summary = 'short'
25
+ #
26
+ # spec.description = <<~DESC
27
+ # long
28
+ # DESC
29
+ #
30
+ # @example
31
+ # # bad
32
+ # store = []
33
+ # protect = lambda do |chunk|
34
+ # store << chunk
35
+ # end
36
+ # text = source
37
+ #
38
+ # # good
39
+ # store = []
40
+ #
41
+ # protect = lambda do |chunk|
42
+ # store << chunk
43
+ # end
44
+ #
45
+ # text = source
46
+ class EmptyLineAroundMultilineAssignment < Base
47
+
48
+ include CheckAssignment
49
+ include EmptyLineAroundMultilineStatement
50
+ extend AutoCorrector
51
+
52
+ MSG_BEFORE = 'Add a blank line before this multiline assignment.'.freeze
53
+ MSG_AFTER = 'Add a blank line after this multiline assignment.'.freeze
54
+
55
+ def check_assignment node, rhs
56
+ return if node.call_type? && !assignment_call?(node)
57
+ return unless bodyish?(rhs)
58
+
59
+ check_empty_lines_around(node)
60
+ end
61
+
62
+ private
63
+
64
+ def assignment_call? node
65
+ node.assignment_method? && node.loc.operator
66
+ end
67
+
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,51 @@
1
+ module RuboCop
2
+ module Cop
3
+ module Yoshiki
4
+ module Layout
5
+ # Isolates a multiline block statement (`do`/`end` or a brace block)
6
+ # from neighboring statements with a blank line.
7
+ #
8
+ # Assigned blocks (`text = gsub(REF) do … end`, `protect = lambda do`)
9
+ # are Yoshiki/Layout/EmptyLineAroundMultilineAssignment — the statement
10
+ # is the assignment. This cop only fires when the block itself is the
11
+ # statement (a sibling in a `begin` sequence).
12
+ #
13
+ # Single-line blocks are left alone.
14
+ #
15
+ # @example
16
+ # # bad
17
+ # prepare
18
+ # items.each do |item|
19
+ # process item
20
+ # end
21
+ # finish
22
+ #
23
+ # # good
24
+ # prepare
25
+ #
26
+ # items.each do |item|
27
+ # process item
28
+ # end
29
+ #
30
+ # finish
31
+ class EmptyLineAroundMultilineBlock < Base
32
+
33
+ include EmptyLineAroundMultilineStatement
34
+ extend AutoCorrector
35
+
36
+ MSG_BEFORE = 'Add a blank line before this multiline block.'.freeze
37
+ MSG_AFTER = 'Add a blank line after this multiline block.'.freeze
38
+
39
+ def on_block node
40
+ return unless block_paragraph?(node)
41
+
42
+ check_empty_lines_around(node)
43
+ end
44
+ alias on_numblock on_block
45
+ alias on_itblock on_block
46
+
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,61 @@
1
+ module RuboCop
2
+ module Cop
3
+ module Yoshiki
4
+ module Layout
5
+ # Isolates a multiline `if` / `unless` / `case` / `while` / `until` /
6
+ # `for` / `begin` statement from neighboring statements with a blank
7
+ # line.
8
+ #
9
+ # Modifier and ternary forms are skipped. An `if` that is the RHS of an
10
+ # assignment is Yoshiki/Layout/EmptyLineAroundMultilineAssignment.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # ref = $1
15
+ # href = resolve_ref(ref)
16
+ # if href
17
+ # link_to href
18
+ # else
19
+ # ref
20
+ # end
21
+ #
22
+ # # good
23
+ # ref = $1
24
+ # href = resolve_ref(ref)
25
+ #
26
+ # if href
27
+ # link_to href
28
+ # else
29
+ # ref
30
+ # end
31
+ class EmptyLineAroundMultilineConditional < Base
32
+
33
+ include EmptyLineAroundMultilineStatement
34
+ extend AutoCorrector
35
+
36
+ MSG_BEFORE = 'Add a blank line before this multiline conditional.'.freeze
37
+ MSG_AFTER = 'Add a blank line after this multiline conditional.'.freeze
38
+
39
+ def on_if node
40
+ inspect_conditional(node)
41
+ end
42
+ alias on_case on_if
43
+ alias on_case_match on_if
44
+ alias on_while on_if
45
+ alias on_until on_if
46
+ alias on_for on_if
47
+ alias on_kwbegin on_if
48
+
49
+ private
50
+
51
+ def inspect_conditional node
52
+ return unless conditional_paragraph?(node)
53
+
54
+ check_empty_lines_around(node)
55
+ end
56
+
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,5 +1,5 @@
1
1
  module Yoshiki
2
2
 
3
- VERSION = '11.0.0-12'.freeze
3
+ VERSION = '11.0.0-13'.freeze
4
4
 
5
5
  end
data/lib/yoshiki.rb CHANGED
@@ -1,7 +1,11 @@
1
1
  require 'yoshiki/version'
2
2
  require 'rubocop'
3
3
  require 'rubocop/cop/yoshiki/keyword_only_arguments'
4
+ require 'rubocop/cop/yoshiki/empty_line_around_multiline_statement'
4
5
  require 'rubocop/cop/yoshiki/layout/empty_line_before_comment'
6
+ require 'rubocop/cop/yoshiki/layout/empty_line_around_multiline_assignment'
7
+ require 'rubocop/cop/yoshiki/layout/empty_line_around_multiline_block'
8
+ require 'rubocop/cop/yoshiki/layout/empty_line_around_multiline_conditional'
5
9
  require 'rubocop/cop/yoshiki/layout/hanging_keyword_arguments'
6
10
  require 'rubocop/cop/yoshiki/lint/parenthesize_value_omission'
7
11
  require 'rubocop/cop/yoshiki/style/it_block_parameter'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yoshiki
3
3
  version: !ruby/object:Gem::Version
4
- version: 11.0.0.pre.12
4
+ version: 11.0.0.pre.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - BM5k
@@ -84,8 +84,13 @@ files:
84
84
  - README.md
85
85
  - Rakefile
86
86
  - bin/console
87
+ - lib/rubocop/cop/yoshiki/empty_line_around_multiline_statement.rb
88
+ - lib/rubocop/cop/yoshiki/empty_line_around_multiline_statement/paragraph.rb
87
89
  - lib/rubocop/cop/yoshiki/haml/sibling_blank_lines.rb
88
90
  - lib/rubocop/cop/yoshiki/keyword_only_arguments.rb
91
+ - lib/rubocop/cop/yoshiki/layout/empty_line_around_multiline_assignment.rb
92
+ - lib/rubocop/cop/yoshiki/layout/empty_line_around_multiline_block.rb
93
+ - lib/rubocop/cop/yoshiki/layout/empty_line_around_multiline_conditional.rb
89
94
  - lib/rubocop/cop/yoshiki/layout/empty_line_before_comment.rb
90
95
  - lib/rubocop/cop/yoshiki/layout/hanging_keyword_arguments.rb
91
96
  - lib/rubocop/cop/yoshiki/lint/parenthesize_value_omission.rb