rubocop-vibe 0.3.0 → 0.4.0
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cdbef6b6693f735e021fc40b2ff54c091942cacc146e6d7314b93597d92d5f0a
|
|
4
|
+
data.tar.gz: 1d612390dcb873c62803cfce7357dc6e73f2dd76cc63adff21478f62d513743f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4b57b54a638c0cd84c19e2096d5792c145964bfab9c96f5f47f6a19d44f17bf8830260b536f6913cacb1f154da30dd26226ac688b3c5fa074fbcd90346cfbfb9
|
|
7
|
+
data.tar.gz: dfec2e07080d666343b0ebd686042299eaa129884fa47c35cab9b0f5ccdd54747d7227edecc970bff1e0e3a1279c4ac8c6eedc7a29e0da54df9fbd3edbed7a8e
|
data/config/default.yml
CHANGED
|
@@ -98,6 +98,12 @@ Vibe/ConsecutiveIndexedAssignmentAlignment:
|
|
|
98
98
|
SafeAutoCorrect: true
|
|
99
99
|
VersionAdded: "0.3.0"
|
|
100
100
|
|
|
101
|
+
Vibe/ConsecutiveInstanceVariableAssignmentAlignment:
|
|
102
|
+
Description: "Enforces alignment of consecutive instance variable assignments at the = operator."
|
|
103
|
+
Enabled: true
|
|
104
|
+
SafeAutoCorrect: true
|
|
105
|
+
VersionAdded: "0.4.0"
|
|
106
|
+
|
|
101
107
|
Vibe/ConsecutiveLetAlignment:
|
|
102
108
|
Description: "Enforces alignment of consecutive let declarations at the { brace."
|
|
103
109
|
Enabled: true
|
|
@@ -122,6 +128,12 @@ Vibe/IsExpectedOneLiner:
|
|
|
122
128
|
SafeAutoCorrect: true
|
|
123
129
|
VersionAdded: "0.1.0"
|
|
124
130
|
|
|
131
|
+
Vibe/LetOrder:
|
|
132
|
+
Description: "Enforces alphabetical ordering of consecutive let declarations."
|
|
133
|
+
Enabled: true
|
|
134
|
+
SafeAutoCorrect: true
|
|
135
|
+
VersionAdded: "0.4.0"
|
|
136
|
+
|
|
125
137
|
Vibe/MultilineHashArgumentStyle:
|
|
126
138
|
Description: "Enforces one-per-line and alphabetical ordering for hash arguments in multiline method calls."
|
|
127
139
|
Enabled: true
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Vibe
|
|
6
|
+
# Enforces alignment of consecutive instance variable assignments at the `=` operator.
|
|
7
|
+
#
|
|
8
|
+
# Consecutive assignments (with no blank lines between) should align their
|
|
9
|
+
# `=` operators for better readability. Groups are broken by blank lines.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# # bad
|
|
13
|
+
# @user = create(:user)
|
|
14
|
+
# @character = create(:character)
|
|
15
|
+
# @input = "test"
|
|
16
|
+
#
|
|
17
|
+
# # good
|
|
18
|
+
# @user = create(:user)
|
|
19
|
+
# @character = create(:character)
|
|
20
|
+
# @input = "test"
|
|
21
|
+
#
|
|
22
|
+
# # good - blank line breaks the group
|
|
23
|
+
# @user = create(:user)
|
|
24
|
+
# @character = create(:character)
|
|
25
|
+
#
|
|
26
|
+
# @service = Users::Activate.new
|
|
27
|
+
# @activation = service.call
|
|
28
|
+
class ConsecutiveInstanceVariableAssignmentAlignment < Base
|
|
29
|
+
extend AutoCorrector
|
|
30
|
+
include AlignmentHelpers
|
|
31
|
+
|
|
32
|
+
MSG = "Align consecutive instance variable assignments at the = operator."
|
|
33
|
+
|
|
34
|
+
# Check block nodes for assignment alignment.
|
|
35
|
+
#
|
|
36
|
+
# @param [RuboCop::AST::Node] node The block node.
|
|
37
|
+
# @return [void]
|
|
38
|
+
def on_block(node)
|
|
39
|
+
if node.body
|
|
40
|
+
check_assignments_in_body(node.body)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
alias on_numblock on_block
|
|
44
|
+
|
|
45
|
+
# Check method definitions for assignment alignment.
|
|
46
|
+
#
|
|
47
|
+
# @param [RuboCop::AST::Node] node The def node.
|
|
48
|
+
# @return [void]
|
|
49
|
+
def on_def(node)
|
|
50
|
+
if node.body
|
|
51
|
+
check_assignments_in_body(node.body)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
alias on_defs on_def
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
# Check assignments in a body node.
|
|
59
|
+
#
|
|
60
|
+
# @param [RuboCop::AST::Node] body The body node.
|
|
61
|
+
# @return [void]
|
|
62
|
+
def check_assignments_in_body(body)
|
|
63
|
+
statements = extract_statements(body)
|
|
64
|
+
|
|
65
|
+
return if statements.size < 2
|
|
66
|
+
|
|
67
|
+
groups = group_consecutive_statements(statements, &:ivasgn_type?)
|
|
68
|
+
|
|
69
|
+
groups.each { |group| check_group_alignment(group) }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Check alignment for a group of assignments.
|
|
73
|
+
#
|
|
74
|
+
# @param [Array<RuboCop::AST::Node>] group The assignment group.
|
|
75
|
+
# @return [void]
|
|
76
|
+
def check_group_alignment(group)
|
|
77
|
+
columns = group.map { |asgn| asgn.loc.operator.column }
|
|
78
|
+
target_column = columns.max
|
|
79
|
+
|
|
80
|
+
group.each do |asgn|
|
|
81
|
+
current_column = asgn.loc.operator.column
|
|
82
|
+
|
|
83
|
+
next if current_column == target_column
|
|
84
|
+
|
|
85
|
+
add_offense(asgn.loc.name) do |corrector|
|
|
86
|
+
autocorrect_alignment(corrector, asgn, target_column)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Auto-correct the alignment of an assignment.
|
|
92
|
+
#
|
|
93
|
+
# @param [RuboCop::AST::Corrector] corrector The corrector.
|
|
94
|
+
# @param [RuboCop::AST::Node] asgn The assignment node.
|
|
95
|
+
# @param [Integer] target_column The target column for alignment.
|
|
96
|
+
# @return [void]
|
|
97
|
+
def autocorrect_alignment(corrector, asgn, target_column)
|
|
98
|
+
variable_name_end = asgn.loc.name.end_pos
|
|
99
|
+
operator_start = asgn.loc.operator.begin_pos
|
|
100
|
+
total_spaces = calculate_total_spaces(asgn, target_column)
|
|
101
|
+
|
|
102
|
+
corrector.replace(
|
|
103
|
+
range_between(variable_name_end, operator_start),
|
|
104
|
+
" " * total_spaces
|
|
105
|
+
)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Calculate total spaces needed for alignment.
|
|
109
|
+
#
|
|
110
|
+
# @param [RuboCop::AST::Node] asgn The assignment node.
|
|
111
|
+
# @param [Integer] target_column The target column for alignment.
|
|
112
|
+
# @return [Integer] The number of spaces (minimum 1).
|
|
113
|
+
def calculate_total_spaces(asgn, target_column)
|
|
114
|
+
current_column = asgn.loc.operator.column
|
|
115
|
+
current_spaces = asgn.loc.operator.begin_pos - asgn.loc.name.end_pos
|
|
116
|
+
spaces_needed = target_column - current_column
|
|
117
|
+
|
|
118
|
+
[1, current_spaces + spaces_needed].max
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Vibe
|
|
6
|
+
# Enforces alphabetical ordering of consecutive `let` declarations.
|
|
7
|
+
#
|
|
8
|
+
# Consecutive `let` declarations (with no blank lines between) should be
|
|
9
|
+
# alphabetically ordered by their symbol name for better readability and
|
|
10
|
+
# easier scanning. Groups are broken by blank lines or non-let statements.
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# # bad
|
|
14
|
+
# let(:subcategory) { create(:category, :subcategory) }
|
|
15
|
+
# let(:budget) { subcategory.budget }
|
|
16
|
+
# let(:category) { subcategory.parent }
|
|
17
|
+
#
|
|
18
|
+
# # good
|
|
19
|
+
# let(:budget) { subcategory.budget }
|
|
20
|
+
# let(:category) { subcategory.parent }
|
|
21
|
+
# let(:subcategory) { create(:category, :subcategory) }
|
|
22
|
+
#
|
|
23
|
+
# # good - blank line breaks the group
|
|
24
|
+
# let(:zebra) { create(:zebra) }
|
|
25
|
+
#
|
|
26
|
+
# let(:apple) { create(:apple) }
|
|
27
|
+
class LetOrder < Base
|
|
28
|
+
extend AutoCorrector
|
|
29
|
+
include SpecFileHelper
|
|
30
|
+
include AlignmentHelpers
|
|
31
|
+
|
|
32
|
+
MSG = "Order consecutive `let` declarations alphabetically."
|
|
33
|
+
|
|
34
|
+
# @!method let_declaration?(node)
|
|
35
|
+
# Check if node is a let/let! declaration.
|
|
36
|
+
def_node_matcher :let_declaration?, <<~PATTERN
|
|
37
|
+
(block (send nil? {:let :let!} (sym _)) ...)
|
|
38
|
+
PATTERN
|
|
39
|
+
|
|
40
|
+
# Check describe/context blocks for let ordering.
|
|
41
|
+
#
|
|
42
|
+
# @param [RuboCop::AST::Node] node The block node.
|
|
43
|
+
# @return [void]
|
|
44
|
+
def on_block(node)
|
|
45
|
+
return unless spec_file?
|
|
46
|
+
return unless describe_or_context?(node)
|
|
47
|
+
return unless node.body
|
|
48
|
+
|
|
49
|
+
check_lets_in_body(node.body)
|
|
50
|
+
end
|
|
51
|
+
alias on_numblock on_block
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
# Check if block is a describe or context block.
|
|
56
|
+
#
|
|
57
|
+
# @param [RuboCop::AST::Node] node The block node.
|
|
58
|
+
# @return [Boolean]
|
|
59
|
+
def describe_or_context?(node)
|
|
60
|
+
node.send_node && %i(describe context).include?(node.method_name)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Check let declarations in a body node.
|
|
64
|
+
#
|
|
65
|
+
# @param [RuboCop::AST::Node] body The body node.
|
|
66
|
+
# @return [void]
|
|
67
|
+
def check_lets_in_body(body)
|
|
68
|
+
statements = extract_statements(body)
|
|
69
|
+
|
|
70
|
+
return if statements.size < 2
|
|
71
|
+
|
|
72
|
+
groups = group_consecutive_statements(statements) { |s| let_declaration?(s) }
|
|
73
|
+
|
|
74
|
+
groups.each { |group| check_group_order(group) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Check ordering for a group of let declarations.
|
|
78
|
+
#
|
|
79
|
+
# @param [Array<RuboCop::AST::Node>] group The let group.
|
|
80
|
+
# @return [void]
|
|
81
|
+
def check_group_order(group)
|
|
82
|
+
return if alphabetically_ordered?(group)
|
|
83
|
+
|
|
84
|
+
violations = find_ordering_violations(group)
|
|
85
|
+
|
|
86
|
+
violations.each do |let|
|
|
87
|
+
add_offense(let.send_node) do |corrector|
|
|
88
|
+
autocorrect(corrector, group)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Check if let declarations are alphabetically ordered.
|
|
94
|
+
#
|
|
95
|
+
# @param [Array<RuboCop::AST::Node>] group The let group.
|
|
96
|
+
# @return [Boolean]
|
|
97
|
+
def alphabetically_ordered?(group)
|
|
98
|
+
names = group.map { |let| extract_let_name(let) }
|
|
99
|
+
|
|
100
|
+
names == names.sort
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Extract the symbol name from a let declaration.
|
|
104
|
+
#
|
|
105
|
+
# @param [RuboCop::AST::Node] let The let block node.
|
|
106
|
+
# @return [String]
|
|
107
|
+
def extract_let_name(let)
|
|
108
|
+
let.send_node.first_argument.value.to_s
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Find let declarations that violate ordering.
|
|
112
|
+
#
|
|
113
|
+
# @param [Array<RuboCop::AST::Node>] group The let group.
|
|
114
|
+
# @return [Array<RuboCop::AST::Node>] Lets that violate ordering.
|
|
115
|
+
def find_ordering_violations(group)
|
|
116
|
+
violations = []
|
|
117
|
+
|
|
118
|
+
group.each_cons(2) do |current, following|
|
|
119
|
+
current_name = extract_let_name(current)
|
|
120
|
+
following_name = extract_let_name(following)
|
|
121
|
+
|
|
122
|
+
violations << following if current_name > following_name
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
violations.uniq
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Auto-correct by reordering let declarations.
|
|
129
|
+
#
|
|
130
|
+
# @param [RuboCop::AST::Corrector] corrector The corrector.
|
|
131
|
+
# @param [Array<RuboCop::AST::Node>] group The let group.
|
|
132
|
+
# @return [void]
|
|
133
|
+
def autocorrect(corrector, group)
|
|
134
|
+
sorted = group.sort_by { |let| extract_let_name(let) }
|
|
135
|
+
|
|
136
|
+
group.each_with_index do |let, index|
|
|
137
|
+
sorted_let = sorted[index]
|
|
138
|
+
|
|
139
|
+
next if let == sorted_let
|
|
140
|
+
|
|
141
|
+
corrector.replace(let, sorted_let.source)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
@@ -9,10 +9,12 @@ require_relative "vibe/class_organization"
|
|
|
9
9
|
require_relative "vibe/consecutive_assignment_alignment"
|
|
10
10
|
require_relative "vibe/consecutive_constant_alignment"
|
|
11
11
|
require_relative "vibe/consecutive_indexed_assignment_alignment"
|
|
12
|
+
require_relative "vibe/consecutive_instance_variable_assignment_alignment"
|
|
12
13
|
require_relative "vibe/consecutive_let_alignment"
|
|
13
14
|
require_relative "vibe/describe_block_order"
|
|
14
15
|
require_relative "vibe/explicit_return_conditional"
|
|
15
16
|
require_relative "vibe/is_expected_one_liner"
|
|
17
|
+
require_relative "vibe/let_order"
|
|
16
18
|
require_relative "vibe/multiline_hash_argument_style"
|
|
17
19
|
require_relative "vibe/no_assigns_attribute_testing"
|
|
18
20
|
require_relative "vibe/no_compound_conditions"
|
data/lib/rubocop/vibe/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubocop-vibe
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tristan Dunn
|
|
@@ -93,10 +93,12 @@ files:
|
|
|
93
93
|
- lib/rubocop/cop/vibe/consecutive_assignment_alignment.rb
|
|
94
94
|
- lib/rubocop/cop/vibe/consecutive_constant_alignment.rb
|
|
95
95
|
- lib/rubocop/cop/vibe/consecutive_indexed_assignment_alignment.rb
|
|
96
|
+
- lib/rubocop/cop/vibe/consecutive_instance_variable_assignment_alignment.rb
|
|
96
97
|
- lib/rubocop/cop/vibe/consecutive_let_alignment.rb
|
|
97
98
|
- lib/rubocop/cop/vibe/describe_block_order.rb
|
|
98
99
|
- lib/rubocop/cop/vibe/explicit_return_conditional.rb
|
|
99
100
|
- lib/rubocop/cop/vibe/is_expected_one_liner.rb
|
|
101
|
+
- lib/rubocop/cop/vibe/let_order.rb
|
|
100
102
|
- lib/rubocop/cop/vibe/mixin/alignment_helpers.rb
|
|
101
103
|
- lib/rubocop/cop/vibe/mixin/spec_file_helper.rb
|
|
102
104
|
- lib/rubocop/cop/vibe/multiline_hash_argument_style.rb
|