rubocop-vibe 0.4.0 → 0.5.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: cdbef6b6693f735e021fc40b2ff54c091942cacc146e6d7314b93597d92d5f0a
4
- data.tar.gz: 1d612390dcb873c62803cfce7357dc6e73f2dd76cc63adff21478f62d513743f
3
+ metadata.gz: f214588afca7a72328401c384b819415ddae3ac7e4fa2c214bfb7225f4253b56
4
+ data.tar.gz: d4a9267839bcd11320ca97f7ef64f17134618f7efee156b4f35b8f1a2a07ad1e
5
5
  SHA512:
6
- metadata.gz: 4b57b54a638c0cd84c19e2096d5792c145964bfab9c96f5f47f6a19d44f17bf8830260b536f6913cacb1f154da30dd26226ac688b3c5fa074fbcd90346cfbfb9
7
- data.tar.gz: dfec2e07080d666343b0ebd686042299eaa129884fa47c35cab9b0f5ccdd54747d7227edecc970bff1e0e3a1279c4ac8c6eedc7a29e0da54df9fbd3edbed7a8e
6
+ metadata.gz: bb99fe49c2b921d70e07a6d2c6c4ea035fa76867a3391803f586575a7631d19d176af76791778aedf33178bfa6cb8f9fa3aebe1a66950b14b88c7dfd3823b101
7
+ data.tar.gz: 4527a16179dbb9b2fa026639f47409a706ba393564b50cc0f6f5544df4b23c9faf6abfc720e319c1a88e92b7f40e2eed553eb720853345134d6d8f754791a9c9
data/config/default.yml CHANGED
@@ -62,6 +62,12 @@ Style/StringLiterals:
62
62
  Style/StringLiteralsInInterpolation:
63
63
  EnforcedStyle: double_quotes
64
64
 
65
+ Vibe/AttrOrder:
66
+ Description: "Enforces alphabetical ordering of attr_reader, attr_writer, and attr_accessor arguments."
67
+ Enabled: true
68
+ SafeAutoCorrect: true
69
+ VersionAdded: "0.5.0"
70
+
65
71
  Vibe/BlankLineAfterAssignment:
66
72
  Description: "Enforces a blank line after variable assignments when followed by other code."
67
73
  Enabled: true
@@ -110,6 +116,18 @@ Vibe/ConsecutiveLetAlignment:
110
116
  SafeAutoCorrect: true
111
117
  VersionAdded: "0.2.0"
112
118
 
119
+ Vibe/ConsecutiveScopeAlignment:
120
+ Description: "Enforces alignment of consecutive scope declarations at the -> arrow."
121
+ Enabled: true
122
+ SafeAutoCorrect: true
123
+ VersionAdded: "0.5.0"
124
+
125
+ Vibe/ConstantAlphaOrder:
126
+ Description: "Enforces alphabetical ordering of consecutive constant declarations by name."
127
+ Enabled: true
128
+ SafeAutoCorrect: false
129
+ VersionAdded: "0.5.0"
130
+
113
131
  Vibe/DescribeBlockOrder:
114
132
  Description: "Enforces consistent ordering of describe blocks in RSpec files."
115
133
  Enabled: true
@@ -128,6 +146,12 @@ Vibe/IsExpectedOneLiner:
128
146
  SafeAutoCorrect: true
129
147
  VersionAdded: "0.1.0"
130
148
 
149
+ Vibe/KeywordArgumentOrder:
150
+ Description: "Enforces alphabetical ordering of keyword arguments and their YARD documentation."
151
+ Enabled: true
152
+ SafeAutoCorrect: true
153
+ VersionAdded: "0.5.0"
154
+
131
155
  Vibe/LetOrder:
132
156
  Description: "Enforces alphabetical ordering of consecutive let declarations."
133
157
  Enabled: true
@@ -196,3 +220,15 @@ Vibe/ServiceCallMethod:
196
220
  Description: "Service objects should define `self.call` and `call` methods."
197
221
  Enabled: true
198
222
  VersionAdded: "0.1.0"
223
+
224
+ Vibe/ValidateAfterValidates:
225
+ Description: "Enforces that validate calls appear after validates declarations in Rails models."
226
+ Enabled: true
227
+ SafeAutoCorrect: true
228
+ VersionAdded: "0.5.0"
229
+
230
+ Vibe/ValidatesAlphaOrder:
231
+ Description: "Enforces alphabetical ordering of consecutive validates declarations by attribute name."
232
+ Enabled: true
233
+ SafeAutoCorrect: true
234
+ VersionAdded: "0.5.0"
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Vibe
6
+ # Enforces alphabetical ordering of arguments to `attr_reader`,
7
+ # `attr_writer`, and `attr_accessor` declarations.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # attr_reader :id, :content, :timestamp, :raw
12
+ #
13
+ # # good
14
+ # attr_reader :content, :id, :raw, :timestamp
15
+ #
16
+ # # bad
17
+ # attr_accessor :zebra, :apple
18
+ #
19
+ # # good
20
+ # attr_accessor :apple, :zebra
21
+ class AttrOrder < Base
22
+ extend AutoCorrector
23
+
24
+ MSG = "Order `%<method>s` arguments alphabetically."
25
+
26
+ ATTR_METHODS = %i(attr_reader attr_writer attr_accessor).freeze
27
+
28
+ # Check attr_* method calls for alphabetical ordering.
29
+ #
30
+ # @param [RuboCop::AST::Node] node The send node.
31
+ # @return [void]
32
+ def on_send(node)
33
+ return unless attr_method?(node)
34
+ return unless node.arguments.size > 1
35
+ return if all_symbols?(node.arguments) && alphabetically_ordered?(node.arguments)
36
+
37
+ add_offense(node, message: format(MSG, method: node.method_name)) do |corrector|
38
+ autocorrect(corrector, node)
39
+ end
40
+ end
41
+ alias on_csend on_send
42
+
43
+ private
44
+
45
+ # Check if the node is an attr_* method call.
46
+ #
47
+ # @param [RuboCop::AST::Node] node The send node.
48
+ # @return [Boolean]
49
+ def attr_method?(node)
50
+ node.receiver.nil? && ATTR_METHODS.include?(node.method_name)
51
+ end
52
+
53
+ # Check if all arguments are symbols.
54
+ #
55
+ # @param [Array<RuboCop::AST::Node>] arguments The arguments.
56
+ # @return [Boolean]
57
+ def all_symbols?(arguments)
58
+ arguments.all?(&:sym_type?)
59
+ end
60
+
61
+ # Check if arguments are alphabetically ordered.
62
+ #
63
+ # @param [Array<RuboCop::AST::Node>] arguments The arguments.
64
+ # @return [Boolean]
65
+ def alphabetically_ordered?(arguments)
66
+ names = arguments.map { |arg| arg.value.to_s }
67
+
68
+ names == names.sort
69
+ end
70
+
71
+ # Auto-correct by reordering arguments alphabetically.
72
+ #
73
+ # @param [RuboCop::AST::Corrector] corrector The corrector.
74
+ # @param [RuboCop::AST::Node] node The send node.
75
+ # @return [void]
76
+ def autocorrect(corrector, node)
77
+ sorted_args = node.arguments.sort_by { |arg| arg.value.to_s }
78
+ sorted_source = sorted_args.map(&:source).join(", ")
79
+
80
+ args_range = node.first_argument.source_range.join(node.last_argument.source_range)
81
+
82
+ corrector.replace(args_range, sorted_source)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -53,6 +53,7 @@ module RuboCop
53
53
  end
54
54
  end
55
55
  alias on_numblock on_block
56
+ alias on_itblock on_block
56
57
 
57
58
  # Check method definitions for assignment statements.
58
59
  #
@@ -51,6 +51,7 @@ module RuboCop
51
51
  end
52
52
  end
53
53
  alias on_numblock on_block
54
+ alias on_itblock on_block
54
55
 
55
56
  private
56
57
 
@@ -36,20 +36,13 @@ module RuboCop
36
36
  class ClassOrganization < Base
37
37
  extend AutoCorrector
38
38
 
39
+ CLASS_MSG = "Class elements should be ordered: includes → constants → initialize → " \
40
+ "class methods → instance methods → protected → private."
39
41
  MODEL_MSG = "Model elements should be ordered: concerns → constants → associations → " \
40
42
  "validations → callbacks → scopes → class methods → instance methods → " \
41
43
  "protected → private."
42
- CLASS_MSG = "Class elements should be ordered: includes → constants → initialize → " \
43
- "class methods → instance methods → protected → private."
44
44
 
45
45
  ASSOCIATIONS = %i(belongs_to has_one has_many has_and_belongs_to_many).freeze
46
- VALIDATIONS = %i(
47
- validates validate validates_each validates_with
48
- validates_absence_of validates_acceptance_of validates_confirmation_of
49
- validates_exclusion_of validates_format_of validates_inclusion_of
50
- validates_length_of validates_numericality_of validates_presence_of
51
- validates_size_of validates_uniqueness_of validates_associated
52
- ).freeze
53
46
  CALLBACKS = %i(
54
47
  before_validation after_validation
55
48
  before_save after_save around_save
@@ -59,6 +52,15 @@ module RuboCop
59
52
  after_commit after_rollback
60
53
  after_initialize after_find after_touch
61
54
  ).freeze
55
+ CLASS_PRIORITIES = {
56
+ concerns: 10,
57
+ constants: 20,
58
+ initialize: 30,
59
+ class_methods: 40,
60
+ instance_methods: 50,
61
+ protected_methods: 60,
62
+ private_methods: 70
63
+ }.freeze
62
64
  MODEL_PRIORITIES = {
63
65
  concerns: 10,
64
66
  constants: 20,
@@ -71,15 +73,13 @@ module RuboCop
71
73
  protected_methods: 90,
72
74
  private_methods: 100
73
75
  }.freeze
74
- CLASS_PRIORITIES = {
75
- concerns: 10,
76
- constants: 20,
77
- initialize: 30,
78
- class_methods: 40,
79
- instance_methods: 50,
80
- protected_methods: 60,
81
- private_methods: 70
82
- }.freeze
76
+ VALIDATIONS = %i(
77
+ validates validate validates_each validates_with
78
+ validates_absence_of validates_acceptance_of validates_confirmation_of
79
+ validates_exclusion_of validates_format_of validates_inclusion_of
80
+ validates_length_of validates_numericality_of validates_presence_of
81
+ validates_size_of validates_uniqueness_of validates_associated
82
+ ).freeze
83
83
  VISIBILITY_CATEGORIES = {
84
84
  protected: :protected_methods,
85
85
  private: :private_methods,
@@ -40,6 +40,7 @@ module RuboCop
40
40
  end
41
41
  end
42
42
  alias on_numblock on_block
43
+ alias on_itblock on_block
43
44
 
44
45
  # Check method definitions for assignment alignment.
45
46
  #
@@ -37,6 +37,7 @@ module RuboCop
37
37
  end
38
38
  end
39
39
  alias on_numblock on_block
40
+ alias on_itblock on_block
40
41
 
41
42
  # Check method definitions for indexed assignment alignment.
42
43
  #
@@ -41,6 +41,7 @@ module RuboCop
41
41
  end
42
42
  end
43
43
  alias on_numblock on_block
44
+ alias on_itblock on_block
44
45
 
45
46
  # Check method definitions for assignment alignment.
46
47
  #
@@ -50,6 +50,7 @@ module RuboCop
50
50
  check_lets_in_body(node.body)
51
51
  end
52
52
  alias on_numblock on_block
53
+ alias on_itblock on_block
53
54
 
54
55
  private
55
56
 
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Vibe
6
+ # Enforces alignment of consecutive `scope` declarations at the `->` arrow.
7
+ #
8
+ # Consecutive `scope` declarations (with no blank lines between) should align
9
+ # their `->` arrows for better readability. Groups are broken by blank lines or
10
+ # non-scope statements.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # scope :between, ->(start, stop) { where(created_at: start..stop) }
15
+ # scope :for_website, ->(website_id) { where(website_id: website_id) }
16
+ #
17
+ # # good
18
+ # scope :between, ->(start, stop) { where(created_at: start..stop) }
19
+ # scope :for_website, ->(website_id) { where(website_id: website_id) }
20
+ #
21
+ # # good - blank line breaks the group
22
+ # scope :between, ->(start, stop) { where(created_at: start..stop) }
23
+ #
24
+ # scope :for_website, ->(website_id) { where(website_id: website_id) }
25
+ class ConsecutiveScopeAlignment < Base
26
+ extend AutoCorrector
27
+ include AlignmentHelpers
28
+
29
+ MSG = "Align consecutive scope declarations at the `->` arrow."
30
+
31
+ # Check class nodes for scope alignment.
32
+ #
33
+ # @param [RuboCop::AST::Node] node The class node.
34
+ # @return [void]
35
+ def on_class(node)
36
+ if node.body
37
+ check_scopes_in_body(node.body)
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ # Check scope declarations in a body node.
44
+ #
45
+ # @param [RuboCop::AST::Node] body The body node.
46
+ # @return [void]
47
+ def check_scopes_in_body(body)
48
+ statements = extract_statements(body)
49
+
50
+ return if statements.size < 2
51
+
52
+ groups = group_consecutive_statements(statements) { |s| scope_declaration?(s) }
53
+
54
+ groups.each { |group| check_group_alignment(group) }
55
+ end
56
+
57
+ # Check if a node is a scope declaration with a lambda.
58
+ #
59
+ # @param [RuboCop::AST::Node] node The node to check.
60
+ # @return [Boolean]
61
+ def scope_declaration?(node)
62
+ return false unless node.send_type?
63
+ return false unless node.method?(:scope)
64
+ return false unless node.receiver.nil?
65
+ return false unless node.arguments[1]&.block_type?
66
+
67
+ node.arguments[1].method?(:lambda)
68
+ end
69
+
70
+ # Get the source range of the `->` arrow in a scope declaration.
71
+ #
72
+ # @param [RuboCop::AST::Node] scope_node The scope send node.
73
+ # @return [Parser::Source::Range]
74
+ def arrow_range(scope_node)
75
+ scope_node.arguments[1].send_node.loc.selector
76
+ end
77
+
78
+ # Check alignment for a group of scope declarations.
79
+ #
80
+ # @param [Array<RuboCop::AST::Node>] group The scope group.
81
+ # @return [void]
82
+ def check_group_alignment(group)
83
+ columns = group.map { |scope| arrow_range(scope).column }
84
+ target_column = columns.max
85
+
86
+ group.each do |scope|
87
+ current_column = arrow_range(scope).column
88
+
89
+ next if current_column == target_column
90
+
91
+ add_offense(scope.first_argument) do |corrector|
92
+ autocorrect_alignment(corrector, scope, target_column)
93
+ end
94
+ end
95
+ end
96
+
97
+ # Auto-correct the alignment of a scope declaration.
98
+ #
99
+ # @param [RuboCop::AST::Corrector] corrector The corrector.
100
+ # @param [RuboCop::AST::Node] scope_node The scope send node.
101
+ # @param [Integer] target_column The target column for alignment.
102
+ # @return [void]
103
+ def autocorrect_alignment(corrector, scope_node, target_column)
104
+ arrow = arrow_range(scope_node)
105
+ comma_end = scope_node.first_argument.source_range.end_pos + 1
106
+ arrow_start = arrow.begin_pos
107
+ total_spaces = calculate_total_spaces(scope_node, target_column)
108
+
109
+ corrector.replace(
110
+ range_between(comma_end, arrow_start),
111
+ " " * total_spaces
112
+ )
113
+ end
114
+
115
+ # Calculate total spaces needed for alignment.
116
+ #
117
+ # @param [RuboCop::AST::Node] scope_node The scope send node.
118
+ # @param [Integer] target_column The target column for alignment.
119
+ # @return [Integer] The number of spaces (minimum 1).
120
+ def calculate_total_spaces(scope_node, target_column)
121
+ arrow = arrow_range(scope_node)
122
+ comma_end = scope_node.first_argument.source_range.end_pos + 1
123
+ current_column = arrow.column
124
+ current_spaces = arrow.begin_pos - comma_end
125
+ spaces_needed = target_column - current_column
126
+
127
+ [1, current_spaces + spaces_needed].max
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Vibe
6
+ # Enforces alphabetical ordering of consecutive constant declarations by name.
7
+ #
8
+ # Consecutive constant declarations (with no blank lines between) should be
9
+ # alphabetically ordered by constant name for better readability and
10
+ # easier scanning. Groups are broken by blank lines or non-constant statements.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # class MyClass
15
+ # ZEBRA = 1
16
+ # ALPHA = 2
17
+ # end
18
+ #
19
+ # # good
20
+ # class MyClass
21
+ # ALPHA = 2
22
+ # ZEBRA = 1
23
+ # end
24
+ #
25
+ # # good - blank line breaks the group
26
+ # class MyClass
27
+ # ZEBRA = 1
28
+ #
29
+ # ALPHA = 2
30
+ # end
31
+ class ConstantAlphaOrder < Base
32
+ extend AutoCorrector
33
+ include AlignmentHelpers
34
+
35
+ MSG = "Order constants alphabetically by name."
36
+
37
+ # Check block nodes for constant ordering.
38
+ #
39
+ # @param [RuboCop::AST::Node] node The block node.
40
+ # @return [void]
41
+ def on_block(node)
42
+ if node.body
43
+ check_constants_in_body(node.body)
44
+ end
45
+ end
46
+ alias on_itblock on_block
47
+ alias on_numblock on_block
48
+
49
+ # Check class nodes for constant ordering.
50
+ #
51
+ # @param [RuboCop::AST::Node] node The class node.
52
+ # @return [void]
53
+ def on_class(node)
54
+ if node.body
55
+ check_constants_in_body(node.body)
56
+ end
57
+ end
58
+
59
+ # Check module nodes for constant ordering.
60
+ #
61
+ # @param [RuboCop::AST::Node] node The module node.
62
+ # @return [void]
63
+ def on_module(node)
64
+ if node.body
65
+ check_constants_in_body(node.body)
66
+ end
67
+ end
68
+
69
+ private
70
+
71
+ # Check constant declarations in a body node.
72
+ #
73
+ # @param [RuboCop::AST::Node] body The body node.
74
+ # @return [void]
75
+ def check_constants_in_body(body)
76
+ statements = extract_statements(body)
77
+
78
+ return if statements.size < 2
79
+
80
+ groups = group_consecutive_statements(statements, &:casgn_type?)
81
+
82
+ groups.each { |group| check_group_order(group) }
83
+ end
84
+
85
+ # Check ordering for a group of constant declarations.
86
+ #
87
+ # @param [Array<RuboCop::AST::Node>] group The constants group.
88
+ # @return [void]
89
+ def check_group_order(group)
90
+ return if alphabetically_ordered?(group)
91
+
92
+ violations = find_ordering_violations(group)
93
+
94
+ violations.each do |constant|
95
+ add_offense(constant) do |corrector|
96
+ autocorrect(corrector, group)
97
+ end
98
+ end
99
+ end
100
+
101
+ # Check if constant declarations are alphabetically ordered.
102
+ #
103
+ # @param [Array<RuboCop::AST::Node>] group The constants group.
104
+ # @return [Boolean]
105
+ def alphabetically_ordered?(group)
106
+ names = group.map { |c| c.name.to_s }
107
+
108
+ names == names.sort
109
+ end
110
+
111
+ # Find constant declarations that violate ordering.
112
+ #
113
+ # @param [Array<RuboCop::AST::Node>] group The constants group.
114
+ # @return [Array<RuboCop::AST::Node>] Constants that violate ordering.
115
+ def find_ordering_violations(group)
116
+ violations = []
117
+
118
+ group.each_cons(2) do |current, following|
119
+ violations << following if current.name.to_s > following.name.to_s
120
+ end
121
+
122
+ violations.uniq
123
+ end
124
+
125
+ # Auto-correct by reordering constant declarations.
126
+ #
127
+ # @param [RuboCop::AST::Corrector] corrector The corrector.
128
+ # @param [Array<RuboCop::AST::Node>] group The constants group.
129
+ # @return [void]
130
+ def autocorrect(corrector, group)
131
+ sorted = group.sort_by { |c| c.name.to_s }
132
+
133
+ group.each_with_index do |constant, index|
134
+ sorted_constant = sorted[index]
135
+
136
+ next if constant == sorted_constant
137
+
138
+ corrector.replace(constant, sorted_constant.source)
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -59,8 +59,8 @@ module RuboCop
59
59
  # Default priority for descriptions that can't be categorized (e.g., constants, variables)
60
60
  DEFAULT_PRIORITY = 999
61
61
 
62
- MODEL_ORDER = %w(class associations validations).freeze
63
62
  CONTROLLER_ACTIONS = %w(index show new create edit update destroy).freeze
63
+ MODEL_ORDER = %w(class associations validations).freeze
64
64
  SPECIAL_SECTIONS = {
65
65
  "class" => 0,
66
66
  "constants" => 5,
@@ -95,6 +95,7 @@ module RuboCop
95
95
  end
96
96
  end
97
97
  alias on_numblock on_block
98
+ alias on_itblock on_block
98
99
 
99
100
  private
100
101
 
@@ -47,8 +47,8 @@ module RuboCop
47
47
  class ExplicitReturnConditional < Base
48
48
  extend AutoCorrector
49
49
 
50
- MSG_TERNARY = "Use explicit `if`/`else`/`end` block instead of ternary operator for return value."
51
50
  MSG_MODIFIER = "Use explicit `if`/`end` block instead of trailing conditional for return value."
51
+ MSG_TERNARY = "Use explicit `if`/`else`/`end` block instead of ternary operator for return value."
52
52
 
53
53
  # Check method definitions for conditional return values.
54
54
  #
@@ -151,12 +151,13 @@ module RuboCop
151
151
  # @param [RuboCop::AST::Node] node The modifier if node.
152
152
  # @return [String]
153
153
  def build_if_block(node)
154
+ keyword = node.unless? && node.condition.type?(:and, :or) ? "unless" : "if"
154
155
  condition = build_condition(node)
155
156
  base_indent = " " * node.loc.column
156
157
  inner_indent = "#{base_indent} "
157
158
 
158
159
  [
159
- "if #{condition}",
160
+ "#{keyword} #{condition}",
160
161
  "#{inner_indent}#{node.if_branch.source}",
161
162
  "#{base_indent}end"
162
163
  ].join("\n")
@@ -168,7 +169,7 @@ module RuboCop
168
169
  # @param [RuboCop::AST::Node] node The if node.
169
170
  # @return [String] The condition source.
170
171
  def build_condition(node)
171
- if node.unless?
172
+ if node.unless? && !node.condition.type?(:and, :or)
172
173
  negate_condition(node.condition)
173
174
  else
174
175
  node.condition.source
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Vibe
6
+ # Enforces alphabetical ordering of keyword arguments in method definitions
7
+ # and their associated YARD `@param` documentation tags.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # # @param id [String] the identifier
12
+ # # @param content [String] the body
13
+ # def initialize(id:, content:)
14
+ # end
15
+ #
16
+ # # good
17
+ # # @param content [String] the body
18
+ # # @param id [String] the identifier
19
+ # def initialize(content:, id:)
20
+ # end
21
+ class KeywordArgumentOrder < Base
22
+ extend AutoCorrector
23
+
24
+ MSG = "Order keyword arguments alphabetically."
25
+
26
+ # Check method definitions for keyword argument ordering.
27
+ #
28
+ # @param [RuboCop::AST::Node] node The def node.
29
+ # @return [void]
30
+ def on_def(node)
31
+ return unless node.arguments?
32
+
33
+ kwargs = extract_keyword_arguments(node)
34
+
35
+ return if kwargs.size < 2
36
+ return if alphabetically_ordered?(kwargs)
37
+
38
+ add_offense(node.arguments) do |corrector|
39
+ autocorrect(corrector, node, kwargs)
40
+ end
41
+ end
42
+ alias on_defs on_def
43
+
44
+ private
45
+
46
+ # Extract keyword arguments from a method definition.
47
+ #
48
+ # @param [RuboCop::AST::Node] node The def node.
49
+ # @return [Array<RuboCop::AST::Node>]
50
+ def extract_keyword_arguments(node)
51
+ node.arguments.select { |arg| arg.type?(:kwarg, :kwoptarg) }
52
+ end
53
+
54
+ # Check if keyword arguments are correctly ordered.
55
+ #
56
+ # Required kwargs come first (alphabetically), then optional kwargs (alphabetically).
57
+ #
58
+ # @param [Array<RuboCop::AST::Node>] kwargs The keyword arguments.
59
+ # @return [Boolean]
60
+ def alphabetically_ordered?(kwargs)
61
+ kwargs == kwargs.sort_by { |arg| kwarg_sort_key(arg) }
62
+ end
63
+
64
+ # Generate a sort key for a keyword argument.
65
+ #
66
+ # Required kwargs come first alphabetically, then optional kwargs alphabetically.
67
+ #
68
+ # @param [RuboCop::AST::Node] arg The argument node.
69
+ # @return [Array]
70
+ def kwarg_sort_key(arg)
71
+ # kwargs array is pre-filtered to only include kwarg/kwoptarg types
72
+ if arg.kwarg_type?
73
+ [0, arg.name.to_s]
74
+ else
75
+ [1, arg.name.to_s]
76
+ end
77
+ end
78
+
79
+ # Auto-correct by reordering keyword arguments and documentation.
80
+ #
81
+ # @param [RuboCop::AST::Corrector] corrector The corrector.
82
+ # @param [RuboCop::AST::Node] node The def node.
83
+ # @param [Array<RuboCop::AST::Node>] kwargs The keyword arguments.
84
+ # @return [void]
85
+ def autocorrect(corrector, node, kwargs)
86
+ autocorrect_arguments(corrector, node)
87
+ autocorrect_documentation(corrector, node, kwargs)
88
+ end
89
+
90
+ # Auto-correct keyword arguments in the method signature.
91
+ #
92
+ # @param [RuboCop::AST::Corrector] corrector The corrector.
93
+ # @param [RuboCop::AST::Node] node The def node.
94
+ # @return [void]
95
+ def autocorrect_arguments(corrector, node)
96
+ args = node.arguments.to_a
97
+ sorted_args = args.sort_by { |arg| sort_key(arg) }
98
+ sorted_source = sorted_args.map(&:source).join(", ")
99
+
100
+ args_range = args.first.source_range.join(args.last.source_range)
101
+
102
+ corrector.replace(args_range, sorted_source)
103
+ end
104
+
105
+ # Generate a sort key for an argument.
106
+ #
107
+ # Positional arguments come first, then required keyword arguments
108
+ # alphabetically, then optional keyword arguments alphabetically.
109
+ #
110
+ # @param [RuboCop::AST::Node] arg The argument node.
111
+ # @return [Array]
112
+ def sort_key(arg)
113
+ case arg.type
114
+ when :kwarg
115
+ [1, arg.name.to_s]
116
+ when :kwoptarg
117
+ [2, arg.name.to_s]
118
+ else
119
+ [0, ""]
120
+ end
121
+ end
122
+
123
+ # Auto-correct YARD @param documentation.
124
+ #
125
+ # @param [RuboCop::AST::Corrector] corrector The corrector.
126
+ # @param [RuboCop::AST::Node] node The def node.
127
+ # @param [Array<RuboCop::AST::Node>] kwargs The keyword arguments.
128
+ # @return [void]
129
+ def autocorrect_documentation(corrector, node, kwargs)
130
+ comments = preceding_comments(node)
131
+
132
+ return if comments.empty?
133
+
134
+ param_comments = extract_param_comments(comments, kwargs)
135
+
136
+ return if param_comments.empty?
137
+
138
+ sorted_kwarg_names = kwargs.sort_by { |arg| sort_key(arg) }.map { |arg| arg.name.to_s }
139
+
140
+ reorder_param_comments(corrector, param_comments, sorted_kwarg_names)
141
+ end
142
+
143
+ # Get comments preceding a node.
144
+ #
145
+ # @param [RuboCop::AST::Node] node The node.
146
+ # @return [Array<Parser::Source::Comment>]
147
+ def preceding_comments(node)
148
+ processed_source.ast_with_comments[node] || []
149
+ end
150
+
151
+ # Extract @param comments for keyword arguments.
152
+ #
153
+ # @param [Array<Parser::Source::Comment>] comments The comments.
154
+ # @param [Array<RuboCop::AST::Node>] kwargs The keyword arguments.
155
+ # @return [Array<Parser::Source::Comment>]
156
+ def extract_param_comments(comments, kwargs)
157
+ kwarg_names = kwargs.map { |arg| arg.name.to_s }
158
+
159
+ comments.select do |comment|
160
+ match = comment.text.match(/@param\s+(\w+)/)
161
+
162
+ match && kwarg_names.include?(match[1])
163
+ end
164
+ end
165
+
166
+ # Reorder @param comments to match argument order.
167
+ #
168
+ # @param [RuboCop::AST::Corrector] corrector The corrector.
169
+ # @param [Array<Parser::Source::Comment>] param_comments The param comments.
170
+ # @param [Array<String>] sorted_kwarg_names The sorted keyword argument names.
171
+ # @return [void]
172
+ def reorder_param_comments(corrector, param_comments, sorted_kwarg_names)
173
+ sorted = param_comments.sort_by do |comment|
174
+ match = comment.text.match(/@param\s+(\w+)/)
175
+
176
+ sorted_kwarg_names.index(match[1]) || Float::INFINITY
177
+ end
178
+
179
+ param_comments.each_with_index do |comment, index|
180
+ sorted_comment = sorted[index]
181
+
182
+ next if comment == sorted_comment
183
+
184
+ corrector.replace(comment, sorted_comment.text)
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -49,6 +49,7 @@ module RuboCop
49
49
  check_lets_in_body(node.body)
50
50
  end
51
51
  alias on_numblock on_block
52
+ alias on_itblock on_block
52
53
 
53
54
  private
54
55
 
@@ -40,9 +40,9 @@ module RuboCop
40
40
  MSG = "Do not disable `%<cops>s`. Fix the issue or configure globally in `.rubocop.yml`."
41
41
  MSG_NO_COP = "Do not use `# rubocop:disable`. Fix the issue or configure globally in `.rubocop.yml`."
42
42
 
43
- DISABLE_PATTERN = /\A#\s*rubocop\s*:\s*disable\b/i
44
- COP_NAME_PATTERN = %r{[A-Za-z]+/[A-Za-z0-9]+}
45
43
  ALL_PATTERN = /\brubocop\s*:\s*disable\s+all\b/i
44
+ COP_NAME_PATTERN = %r{[A-Za-z]+/[A-Za-z0-9]+}
45
+ DISABLE_PATTERN = /\A#\s*rubocop\s*:\s*disable\b/i
46
46
 
47
47
  # Check for rubocop:disable comments.
48
48
  #
@@ -38,12 +38,12 @@ module RuboCop
38
38
  class NoSkippedTests < Base
39
39
  include SpecFileHelper
40
40
 
41
- MSG_SKIP = "Do not skip tests. Implement or delete the test."
42
41
  MSG_PENDING = "Do not mark tests as pending. Implement or delete the test."
42
+ MSG_SKIP = "Do not skip tests. Implement or delete the test."
43
43
  MSG_XMETHOD = "Do not use `%<method>s`. Implement or delete the test."
44
44
 
45
- SKIP_METHODS = %i(skip).freeze
46
45
  PENDING_METHODS = %i(pending).freeze
46
+ SKIP_METHODS = %i(skip).freeze
47
47
  X_METHODS = %i(xit xspecify xexample xscenario xdescribe xcontext xfeature).freeze
48
48
 
49
49
  # @!method skip_call?(node)
@@ -66,6 +66,7 @@ module RuboCop
66
66
  end
67
67
  end
68
68
  alias on_numblock on_block
69
+ alias on_itblock on_block
69
70
 
70
71
  private
71
72
 
@@ -72,25 +72,28 @@ module RuboCop
72
72
  # @param [RuboCop::AST::Node] node The if node.
73
73
  # @return [String] The replacement code.
74
74
  def build_replacement(node)
75
+ keyword = node.unless? && node.condition.type?(:and, :or) ? "unless" : "if"
75
76
  condition = build_condition(node)
76
77
  raise_source = node.body.source
77
78
  base_indent = " " * node.loc.column
78
79
  inner_indent = "#{base_indent} "
79
80
 
80
81
  [
81
- "if #{condition}",
82
+ "#{keyword} #{condition}",
82
83
  "#{inner_indent}#{raise_source}",
83
84
  "#{base_indent}end"
84
85
  ].join("\n")
85
86
  end
86
87
 
87
- # Build the condition for the if block.
88
- # For unless, negate the condition. For if, keep it as is.
88
+ # Build the condition for the if/unless block.
89
+ # For unless with a compound condition, keep it as-is (paired with unless keyword).
90
+ # For unless with a simple condition, negate it.
91
+ # For if, keep as-is.
89
92
  #
90
93
  # @param [RuboCop::AST::Node] node The if node.
91
94
  # @return [String] The condition source.
92
95
  def build_condition(node)
93
- if node.unless?
96
+ if node.unless? && !node.condition.type?(:and, :or)
94
97
  "!#{node.condition.source}"
95
98
  else
96
99
  node.condition.source
@@ -45,6 +45,7 @@ module RuboCop
45
45
  end
46
46
  end
47
47
  alias on_numblock on_block
48
+ alias on_itblock on_block
48
49
 
49
50
  private
50
51
 
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Vibe
6
+ # Enforces that `validate` calls appear after `validates` declarations.
7
+ #
8
+ # Within a consecutive block of validates-family calls (no blank lines
9
+ # between), all `validate :method` calls must come after all `validates*`
10
+ # declarations. The order of `validate` calls relative to each other is
11
+ # not enforced.
12
+ #
13
+ # @example
14
+ # # bad
15
+ # class User < ApplicationRecord
16
+ # validate :check_expiry
17
+ # validates :name, presence: true
18
+ # end
19
+ #
20
+ # # good
21
+ # class User < ApplicationRecord
22
+ # validates :name, presence: true
23
+ # validate :check_expiry
24
+ # end
25
+ #
26
+ # # good - blank line breaks the group
27
+ # class User < ApplicationRecord
28
+ # validate :check_expiry
29
+ #
30
+ # validates :name, presence: true
31
+ # end
32
+ class ValidateAfterValidates < Base
33
+ extend AutoCorrector
34
+ include AlignmentHelpers
35
+
36
+ MSG = "Place `validate` calls after `validates` declarations."
37
+
38
+ VALIDATES_METHODS = %i(
39
+ validates validates_each validates_with
40
+ validates_absence_of validates_acceptance_of validates_confirmation_of
41
+ validates_exclusion_of validates_format_of validates_inclusion_of
42
+ validates_length_of validates_numericality_of validates_presence_of
43
+ validates_size_of validates_uniqueness_of validates_associated
44
+ ).freeze
45
+
46
+ VALIDATE_METHOD = :validate
47
+
48
+ # Check class nodes for validate/validates ordering.
49
+ #
50
+ # @param [RuboCop::AST::Node] node The class node.
51
+ # @return [void]
52
+ def on_class(node)
53
+ return unless rails_model?(node)
54
+ return unless node.body
55
+
56
+ check_validates_in_body(node.body)
57
+ end
58
+
59
+ private
60
+
61
+ # Check validates-family declarations in a body node.
62
+ #
63
+ # @param [RuboCop::AST::Node] body The body node.
64
+ # @return [void]
65
+ def check_validates_in_body(body)
66
+ statements = extract_statements(body)
67
+
68
+ return if statements.size < 2
69
+
70
+ groups = group_consecutive_statements(statements) { |s| validates_family?(s) }
71
+
72
+ groups.each { |group| check_group_order(group) }
73
+ end
74
+
75
+ # Check if a node is a validates-family declaration.
76
+ #
77
+ # @param [RuboCop::AST::Node] node The node to check.
78
+ # @return [Boolean]
79
+ def validates_family?(node)
80
+ if node.send_type?
81
+ VALIDATES_METHODS.include?(node.method_name) || node.method?(VALIDATE_METHOD)
82
+ else
83
+ false
84
+ end
85
+ end
86
+
87
+ # Check ordering for a group of validates-family declarations.
88
+ #
89
+ # @param [Array<RuboCop::AST::Node>] group The validates group.
90
+ # @return [void]
91
+ def check_group_order(group)
92
+ violations = find_violations(group)
93
+
94
+ return if violations.empty?
95
+
96
+ violations.each do |validate|
97
+ add_offense(validate) do |corrector|
98
+ autocorrect(corrector, group)
99
+ end
100
+ end
101
+ end
102
+
103
+ # Find validate calls that appear before validates* declarations.
104
+ #
105
+ # @param [Array<RuboCop::AST::Node>] group The validates group.
106
+ # @return [Array<RuboCop::AST::Node>] Validate nodes that violate ordering.
107
+ def find_violations(group)
108
+ last_validates_index = group.rindex { |n| VALIDATES_METHODS.include?(n.method_name) }
109
+
110
+ return [] if last_validates_index.nil?
111
+
112
+ group.each_with_index.filter_map do |node, index|
113
+ node if index < last_validates_index && node.method?(VALIDATE_METHOD)
114
+ end
115
+ end
116
+
117
+ # Auto-correct by moving validate calls after validates* declarations.
118
+ #
119
+ # Preserves relative order within each tier.
120
+ #
121
+ # @param [RuboCop::AST::Corrector] corrector The corrector.
122
+ # @param [Array<RuboCop::AST::Node>] group The validates group.
123
+ # @return [void]
124
+ def autocorrect(corrector, group)
125
+ validates_nodes = group.select { |n| VALIDATES_METHODS.include?(n.method_name) }
126
+ validate_nodes = group.select { |n| n.method?(VALIDATE_METHOD) }
127
+ sorted = validates_nodes + validate_nodes
128
+
129
+ group.each_with_index do |node, index|
130
+ sorted_node = sorted[index]
131
+
132
+ next if node == sorted_node
133
+
134
+ corrector.replace(node, sorted_node.source)
135
+ end
136
+ end
137
+
138
+ # Check if this is a Rails model.
139
+ #
140
+ # @param [RuboCop::AST::Node] node The class node.
141
+ # @return [Boolean]
142
+ def rails_model?(node)
143
+ if node.parent_class
144
+ parent_name = node.parent_class.const_name.to_s
145
+ parent_name == "ApplicationRecord" ||
146
+ parent_name == "ActiveRecord::Base" ||
147
+ parent_name.end_with?("::ApplicationRecord")
148
+ else
149
+ false
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Vibe
6
+ # Enforces alphabetical ordering of consecutive `validates` declarations.
7
+ #
8
+ # Consecutive `validates` declarations (with no blank lines between) should be
9
+ # alphabetically ordered by the first attribute name for better readability and
10
+ # easier scanning. Groups are broken by blank lines or non-validates statements.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # class User < ApplicationRecord
15
+ # validates :name, presence: true
16
+ # validates :age, numericality: true
17
+ # end
18
+ #
19
+ # # good
20
+ # class User < ApplicationRecord
21
+ # validates :age, numericality: true
22
+ # validates :name, presence: true
23
+ # end
24
+ #
25
+ # # good - blank line breaks the group
26
+ # class User < ApplicationRecord
27
+ # validates :z, presence: true
28
+ #
29
+ # validates :a, presence: true
30
+ # end
31
+ class ValidatesAlphaOrder < Base
32
+ extend AutoCorrector
33
+ include AlignmentHelpers
34
+
35
+ MSG = "Order validates declarations alphabetically by attribute name."
36
+
37
+ VALIDATES_METHODS = %i(
38
+ validates validates_each validates_with
39
+ validates_absence_of validates_acceptance_of validates_confirmation_of
40
+ validates_exclusion_of validates_format_of validates_inclusion_of
41
+ validates_length_of validates_numericality_of validates_presence_of
42
+ validates_size_of validates_uniqueness_of validates_associated
43
+ ).freeze
44
+
45
+ # Check class nodes for validates ordering.
46
+ #
47
+ # @param [RuboCop::AST::Node] node The class node.
48
+ # @return [void]
49
+ def on_class(node)
50
+ return unless rails_model?(node)
51
+ return unless node.body
52
+
53
+ check_validates_in_body(node.body)
54
+ end
55
+
56
+ private
57
+
58
+ # Check validates declarations in a body node.
59
+ #
60
+ # @param [RuboCop::AST::Node] body The body node.
61
+ # @return [void]
62
+ def check_validates_in_body(body)
63
+ statements = extract_statements(body)
64
+
65
+ return if statements.size < 2
66
+
67
+ groups = group_consecutive_statements(statements) { |s| validates_declaration?(s) }
68
+
69
+ groups.each { |group| check_group_order(group) }
70
+ end
71
+
72
+ # Check if a node is a validates declaration.
73
+ #
74
+ # @param [RuboCop::AST::Node] node The node to check.
75
+ # @return [Boolean]
76
+ def validates_declaration?(node)
77
+ if node.send_type?
78
+ VALIDATES_METHODS.include?(node.method_name)
79
+ else
80
+ false
81
+ end
82
+ end
83
+
84
+ # Check ordering for a group of validates declarations.
85
+ #
86
+ # @param [Array<RuboCop::AST::Node>] group The validates group.
87
+ # @return [void]
88
+ def check_group_order(group)
89
+ return if alphabetically_ordered?(group)
90
+
91
+ violations = find_ordering_violations(group)
92
+
93
+ violations.each do |validates|
94
+ add_offense(validates) do |corrector|
95
+ autocorrect(corrector, group)
96
+ end
97
+ end
98
+ end
99
+
100
+ # Check if validates declarations are alphabetically ordered.
101
+ #
102
+ # @param [Array<RuboCop::AST::Node>] group The validates group.
103
+ # @return [Boolean]
104
+ def alphabetically_ordered?(group)
105
+ names = group.map { |v| extract_validates_name(v) }
106
+
107
+ names == names.sort
108
+ end
109
+
110
+ # Extract the attribute name from a validates declaration.
111
+ #
112
+ # @param [RuboCop::AST::Node] node The validates node.
113
+ # @return [String]
114
+ def extract_validates_name(node)
115
+ node.first_argument.value.to_s
116
+ end
117
+
118
+ # Find validates declarations that violate ordering.
119
+ #
120
+ # @param [Array<RuboCop::AST::Node>] group The validates group.
121
+ # @return [Array<RuboCop::AST::Node>] Validates that violate ordering.
122
+ def find_ordering_violations(group)
123
+ violations = []
124
+
125
+ group.each_cons(2) do |current, following|
126
+ violations << following if extract_validates_name(current) > extract_validates_name(following)
127
+ end
128
+
129
+ violations.uniq
130
+ end
131
+
132
+ # Auto-correct by reordering validates declarations.
133
+ #
134
+ # @param [RuboCop::AST::Corrector] corrector The corrector.
135
+ # @param [Array<RuboCop::AST::Node>] group The validates group.
136
+ # @return [void]
137
+ def autocorrect(corrector, group)
138
+ sorted = group.sort_by { |v| extract_validates_name(v) }
139
+
140
+ group.each_with_index do |validates, index|
141
+ sorted_validates = sorted[index]
142
+
143
+ next if validates == sorted_validates
144
+
145
+ corrector.replace(validates, sorted_validates.source)
146
+ end
147
+ end
148
+
149
+ # Check if this is a Rails model.
150
+ #
151
+ # @param [RuboCop::AST::Node] node The class node.
152
+ # @return [Boolean]
153
+ def rails_model?(node)
154
+ if node.parent_class
155
+ parent_name = node.parent_class.const_name.to_s
156
+ parent_name == "ApplicationRecord" ||
157
+ parent_name == "ActiveRecord::Base" ||
158
+ parent_name.end_with?("::ApplicationRecord")
159
+ else
160
+ false
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -3,6 +3,7 @@
3
3
  require_relative "vibe/mixin/alignment_helpers"
4
4
  require_relative "vibe/mixin/spec_file_helper"
5
5
 
6
+ require_relative "vibe/attr_order"
6
7
  require_relative "vibe/blank_line_after_assignment"
7
8
  require_relative "vibe/blank_line_before_expectation"
8
9
  require_relative "vibe/class_organization"
@@ -11,9 +12,12 @@ require_relative "vibe/consecutive_constant_alignment"
11
12
  require_relative "vibe/consecutive_indexed_assignment_alignment"
12
13
  require_relative "vibe/consecutive_instance_variable_assignment_alignment"
13
14
  require_relative "vibe/consecutive_let_alignment"
15
+ require_relative "vibe/consecutive_scope_alignment"
16
+ require_relative "vibe/constant_alpha_order"
14
17
  require_relative "vibe/describe_block_order"
15
18
  require_relative "vibe/explicit_return_conditional"
16
19
  require_relative "vibe/is_expected_one_liner"
20
+ require_relative "vibe/keyword_argument_order"
17
21
  require_relative "vibe/let_order"
18
22
  require_relative "vibe/multiline_hash_argument_style"
19
23
  require_relative "vibe/no_assigns_attribute_testing"
@@ -26,3 +30,5 @@ require_relative "vibe/raise_unless_block"
26
30
  require_relative "vibe/rspec_before_block_style"
27
31
  require_relative "vibe/rspec_stub_chain_style"
28
32
  require_relative "vibe/service_call_method"
33
+ require_relative "vibe/validate_after_validates"
34
+ require_relative "vibe/validates_alpha_order"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Vibe
5
- VERSION = "0.4.0"
5
+ VERSION = "0.5.0"
6
6
  end
7
7
  end
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.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tristan Dunn
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 1.82.1
32
+ version: 1.85.0
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: 1.82.1
39
+ version: 1.85.0
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: rubocop-performance
42
42
  requirement: !ruby/object:Gem::Requirement
@@ -71,14 +71,14 @@ dependencies:
71
71
  requirements:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
- version: 3.8.0
74
+ version: 3.9.0
75
75
  type: :runtime
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - ">="
80
80
  - !ruby/object:Gem::Version
81
- version: 3.8.0
81
+ version: 3.9.0
82
82
  description: A set of custom cops to use on AI generated code.
83
83
  email: hello@tristandunn.com
84
84
  executables: []
@@ -87,6 +87,7 @@ extra_rdoc_files: []
87
87
  files:
88
88
  - config/default.yml
89
89
  - lib/rubocop-vibe.rb
90
+ - lib/rubocop/cop/vibe/attr_order.rb
90
91
  - lib/rubocop/cop/vibe/blank_line_after_assignment.rb
91
92
  - lib/rubocop/cop/vibe/blank_line_before_expectation.rb
92
93
  - lib/rubocop/cop/vibe/class_organization.rb
@@ -95,9 +96,12 @@ files:
95
96
  - lib/rubocop/cop/vibe/consecutive_indexed_assignment_alignment.rb
96
97
  - lib/rubocop/cop/vibe/consecutive_instance_variable_assignment_alignment.rb
97
98
  - lib/rubocop/cop/vibe/consecutive_let_alignment.rb
99
+ - lib/rubocop/cop/vibe/consecutive_scope_alignment.rb
100
+ - lib/rubocop/cop/vibe/constant_alpha_order.rb
98
101
  - lib/rubocop/cop/vibe/describe_block_order.rb
99
102
  - lib/rubocop/cop/vibe/explicit_return_conditional.rb
100
103
  - lib/rubocop/cop/vibe/is_expected_one_liner.rb
104
+ - lib/rubocop/cop/vibe/keyword_argument_order.rb
101
105
  - lib/rubocop/cop/vibe/let_order.rb
102
106
  - lib/rubocop/cop/vibe/mixin/alignment_helpers.rb
103
107
  - lib/rubocop/cop/vibe/mixin/spec_file_helper.rb
@@ -112,6 +116,8 @@ files:
112
116
  - lib/rubocop/cop/vibe/rspec_before_block_style.rb
113
117
  - lib/rubocop/cop/vibe/rspec_stub_chain_style.rb
114
118
  - lib/rubocop/cop/vibe/service_call_method.rb
119
+ - lib/rubocop/cop/vibe/validate_after_validates.rb
120
+ - lib/rubocop/cop/vibe/validates_alpha_order.rb
115
121
  - lib/rubocop/cop/vibe_cops.rb
116
122
  - lib/rubocop/vibe.rb
117
123
  - lib/rubocop/vibe/plugin.rb
@@ -138,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
144
  - !ruby/object:Gem::Version
139
145
  version: '0'
140
146
  requirements: []
141
- rubygems_version: 4.0.4
147
+ rubygems_version: 4.0.5
142
148
  specification_version: 4
143
149
  summary: A set of custom cops to use on AI generated code.
144
150
  test_files: []