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 +4 -4
- data/.yoshiki-ruby.yml +6 -0
- data/Gemfile.lock +1 -1
- data/lib/rubocop/cop/yoshiki/empty_line_around_multiline_statement/paragraph.rb +81 -0
- data/lib/rubocop/cop/yoshiki/empty_line_around_multiline_statement.rb +94 -0
- data/lib/rubocop/cop/yoshiki/layout/empty_line_around_multiline_assignment.rb +72 -0
- data/lib/rubocop/cop/yoshiki/layout/empty_line_around_multiline_block.rb +51 -0
- data/lib/rubocop/cop/yoshiki/layout/empty_line_around_multiline_conditional.rb +61 -0
- data/lib/yoshiki/version.rb +1 -1
- data/lib/yoshiki.rb +4 -0
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 35fa2afafcdcf1908eb5090d37ab33868394bc5bd449e14bcb24015d4bedb038
|
|
4
|
+
data.tar.gz: e70d04d068aa8805eb5c01cad47cfa7225d93d7b9a2a1e9828ee24ed11ccb5e3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
@@ -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
|
data/lib/yoshiki/version.rb
CHANGED
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.
|
|
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
|