betterlint 1.13.0 → 1.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +53 -0
- data/config/default.yml +35 -4
- data/lib/rubocop/cop/betterment/direct_delayed_enqueue.rb +22 -0
- data/lib/rubocop/cop/betterment/internals_protection.rb +85 -0
- data/lib/rubocop/cop/betterment/non_standard_actions.rb +4 -4
- data/lib/rubocop/cop/betterment/render_status.rb +4 -4
- data/lib/rubocop/cop/betterment/utils/parser.rb +18 -18
- data/lib/rubocop/cop/betterment.rb +2 -0
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 834ddcd8893844db2ccbff0a1c0379f40e47f12fbbff9859831c342df1266d34
|
4
|
+
data.tar.gz: 8b8b7c4d49d7a961f042fc6941f6f55085b77a502441eb1c6ba7dfb8aa1af9cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1db7904622a80b0271e05f33f36c4667f720a9fd13253422dba34c70ecd2ef0f6973255d5506475cd942e3ab72b353a61121da4ed4fa871d2b546228881324f
|
7
|
+
data.tar.gz: 3cf27adfc7561156c5a11a5a54c58b1bb471e5e944aed955220aaa8c383bf0e155eeb56aa514d537da317e08943ac9b330bb510d8fcf85cc8f6bbe6d7dcbc1dc
|
data/README.md
CHANGED
@@ -101,6 +101,15 @@ Betterment/UnscopedFind:
|
|
101
101
|
- ZipCode
|
102
102
|
```
|
103
103
|
|
104
|
+
### Betterment/DirectDelayedEnqueue
|
105
|
+
|
106
|
+
This cop flags code that uses `Object#delay` or `Delayed::Job.enqueue`. Please use `ActiveJob` instead.
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
user.delay.save!
|
110
|
+
Delayed::Job.enqueue(MyJob.new)
|
111
|
+
```
|
112
|
+
|
104
113
|
### Betterment/DynamicParams
|
105
114
|
|
106
115
|
This cop flags code that accesses parameters whose names may be dynamically generated, such as a list of parameters in an a global variable or a return value from a method. In some cases, dynamically accessing parameter names can obscure what the client is expected to send and may make it difficult to reason about the code, both manually and programmatically. For example:
|
@@ -121,6 +130,50 @@ end
|
|
121
130
|
```
|
122
131
|
|
123
132
|
All three `params.permit` calls will be flagged.
|
133
|
+
### Betterment/InternalsProtection
|
134
|
+
|
135
|
+
This cop is not enabled by default, and must be enabled from your `.rubocop.yml` file:
|
136
|
+
|
137
|
+
```yaml
|
138
|
+
Betterment/InternalsProtection:
|
139
|
+
Enabled: true
|
140
|
+
```
|
141
|
+
|
142
|
+
This cop enforces constants defined within `Internals` modules from being referenced from other modules.
|
143
|
+
|
144
|
+
For example, if you have a `Widget` ActiveRecord class that you don't want to be used directly,
|
145
|
+
you can place it into an Internals module such as:
|
146
|
+
```ruby
|
147
|
+
class Widgets::Internals::Widget < ApplicationRecord
|
148
|
+
end
|
149
|
+
```
|
150
|
+
|
151
|
+
Code outside of the `Widgets` module will not be allowed to reference Widget:
|
152
|
+
```ruby
|
153
|
+
class WidgetsController < ApplicationController
|
154
|
+
def create
|
155
|
+
Widgets::Internals::Widget.create!
|
156
|
+
^^^^^^^^^^^^^^^^^^ Internal constants may only be referenced from code within its containing module. [...]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
Non-Internal code within the module can be used to manage access.
|
162
|
+
```ruby
|
163
|
+
class Widgets::WidgetCreation
|
164
|
+
def save!
|
165
|
+
Widgets::Internals::Widget.create!
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
class WidgetsController < ApplicationController
|
170
|
+
def create
|
171
|
+
Widgets::WidgetCreation.new.save!
|
172
|
+
end
|
173
|
+
end
|
174
|
+
```
|
175
|
+
|
176
|
+
This cop inspects all direct constant references, and the `class_name` attribute on ActiveRecord associations.
|
124
177
|
|
125
178
|
### Betterment/UnsafeJob
|
126
179
|
|
data/config/default.yml
CHANGED
@@ -32,6 +32,9 @@ Betterment/AuthorizationInController:
|
|
32
32
|
Enabled: false
|
33
33
|
StyleGuide: '#bettermentauthorizationincontroller'
|
34
34
|
|
35
|
+
Betterment/DirectDelayedEnqueue:
|
36
|
+
StyleGuide: '#bettermentdirectdelayedenqueue'
|
37
|
+
|
35
38
|
Betterment/DynamicParams:
|
36
39
|
StyleGuide: '#bettermentdynamicparams'
|
37
40
|
|
@@ -98,15 +101,43 @@ FactoryBot/ConsistentParenthesesStyle:
|
|
98
101
|
FactoryBot/SyntaxMethods:
|
99
102
|
Enabled: false
|
100
103
|
|
104
|
+
Layout/ArgumentAlignment:
|
105
|
+
EnforcedStyle: with_fixed_indentation
|
106
|
+
|
107
|
+
Layout/ArrayAlignment:
|
108
|
+
EnforcedStyle: with_fixed_indentation
|
109
|
+
|
101
110
|
Layout/CaseIndentation:
|
102
|
-
|
111
|
+
EnforcedStyle: end
|
112
|
+
IndentOneStep: false
|
103
113
|
|
104
114
|
Layout/ClosingParenthesisIndentation:
|
105
115
|
Enabled: true
|
106
116
|
|
117
|
+
Layout/EndAlignment:
|
118
|
+
EnforcedStyleAlignWith: variable
|
119
|
+
|
120
|
+
Layout/FirstArgumentIndentation:
|
121
|
+
EnforcedStyle: consistent
|
122
|
+
|
107
123
|
Layout/FirstArrayElementIndentation:
|
108
124
|
EnforcedStyle: consistent
|
109
125
|
|
126
|
+
Layout/FirstHashElementIndentation:
|
127
|
+
EnforcedStyle: consistent
|
128
|
+
|
129
|
+
Layout/FirstParameterIndentation:
|
130
|
+
Enabled: false
|
131
|
+
|
132
|
+
Layout/LineContinuationLeadingSpace:
|
133
|
+
Enabled: false
|
134
|
+
|
135
|
+
Layout/LineContinuationSpacing:
|
136
|
+
Enabled: true
|
137
|
+
|
138
|
+
Layout/LineEndStringConcatenationIndentation:
|
139
|
+
Enabled: false
|
140
|
+
|
110
141
|
Layout/LineLength:
|
111
142
|
Max: 140
|
112
143
|
|
@@ -117,11 +148,11 @@ Layout/MultilineOperationIndentation:
|
|
117
148
|
EnforcedStyle: indented
|
118
149
|
|
119
150
|
Layout/ParameterAlignment:
|
120
|
-
Enabled:
|
151
|
+
Enabled: true
|
152
|
+
EnforcedStyle: with_fixed_indentation
|
121
153
|
|
122
|
-
# Disabling because of a bug in rubocop: https://github.com/rubocop-hq/rubocop/issues/6918
|
123
154
|
Layout/RescueEnsureAlignment:
|
124
|
-
Enabled:
|
155
|
+
Enabled: true
|
125
156
|
|
126
157
|
Lint/AmbiguousBlockAssociation:
|
127
158
|
Exclude:
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Betterment
|
6
|
+
class DirectDelayedEnqueue < Base
|
7
|
+
DELAY_MESSAGE = 'Please use Active Job instead of using `Object#delay`'
|
8
|
+
ENQUEUE_MESSAGE = 'Please use Active Job instead of using `Delayed::Job.enqueue`'
|
9
|
+
|
10
|
+
# @!method enqueue?(node)
|
11
|
+
def_node_matcher :enqueue?, <<-PATTERN
|
12
|
+
(send (const (const nil? :Delayed) :Job) :enqueue ...)
|
13
|
+
PATTERN
|
14
|
+
|
15
|
+
def on_send(node)
|
16
|
+
add_offense(node, message: DELAY_MESSAGE) if node.method?(:delay)
|
17
|
+
add_offense(node, message: ENQUEUE_MESSAGE) if enqueue?(node)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Betterment
|
6
|
+
class InternalsProtection < Base
|
7
|
+
MSG = <<~END.gsub(/\s+/, " ")
|
8
|
+
Internal constants may only be referenced from code within its containing module.
|
9
|
+
Constants defined within a module's Internals submodule may only be referenced by code in that module,
|
10
|
+
or nested classes and modules
|
11
|
+
(e.g. MyModule::Internals::MyClass may only be referenced from code in MyModule or MyModule::MyPublicClass).
|
12
|
+
END
|
13
|
+
|
14
|
+
# @!method association_with_class_name(node)
|
15
|
+
def_node_matcher :association_with_class_name, <<-PATTERN
|
16
|
+
(send nil? {:has_many :has_one :belongs_to} ... (hash <(pair (sym :class_name) ${str}) ...>))
|
17
|
+
PATTERN
|
18
|
+
|
19
|
+
# @!method rspec_describe(node)
|
20
|
+
def_node_matcher :rspec_describe, <<-PATTERN
|
21
|
+
(block (send (const nil? :RSpec) :describe ${const | str}) ...)
|
22
|
+
PATTERN
|
23
|
+
|
24
|
+
def on_const(node)
|
25
|
+
if node.children[1] == :Internals
|
26
|
+
module_path = const_path(node)
|
27
|
+
|
28
|
+
ensure_allowed_reference!(node, module_path)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_send(node)
|
33
|
+
class_name_node = association_with_class_name(node)
|
34
|
+
return unless class_name_node
|
35
|
+
|
36
|
+
full_path = string_path(class_name_node)
|
37
|
+
internals_index = full_path.find_index(:Internals)
|
38
|
+
if internals_index
|
39
|
+
module_path = full_path.take(internals_index)
|
40
|
+
ensure_allowed_reference!(class_name_node, module_path)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def ensure_allowed_reference!(node, module_path)
|
47
|
+
return if module_path.empty?
|
48
|
+
|
49
|
+
unless definition_context_path(node).each_cons(module_path.size).any?(module_path)
|
50
|
+
add_offense(node)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def const_path(const_node)
|
55
|
+
const_node.each_descendant(:const, :cbase).map { |n| n.children[1] }.reverse
|
56
|
+
end
|
57
|
+
|
58
|
+
def string_path(string_node)
|
59
|
+
string_node.children[0].split('::').map { |name| name == '' ? nil : name.to_sym }
|
60
|
+
end
|
61
|
+
|
62
|
+
def definition_context_path(node)
|
63
|
+
rspec_context_path(node) || module_class_definition_context_path(node)
|
64
|
+
end
|
65
|
+
|
66
|
+
def module_class_definition_context_path(node)
|
67
|
+
node.each_ancestor(:class, :module).flat_map { |anc|
|
68
|
+
anc.children[0].each_node(:const, :cbase).map { |c| c.children[1] }
|
69
|
+
}.push(nil).reverse
|
70
|
+
end
|
71
|
+
|
72
|
+
def rspec_context_path(node)
|
73
|
+
rspec_described_class = node.each_ancestor(:block).filter_map { |ancestor|
|
74
|
+
rspec_describe(ancestor)
|
75
|
+
}.first
|
76
|
+
case rspec_described_class&.type
|
77
|
+
when :const then const_path(rspec_described_class)
|
78
|
+
when :str then string_path(rspec_described_class)
|
79
|
+
else nil # rubocop:disable Style/EmptyElse
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -53,10 +53,10 @@ module RuboCop
|
|
53
53
|
if route
|
54
54
|
(path, param, value) = route
|
55
55
|
action = case param
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
when :to then value.first.split('#').last
|
57
|
+
when :action then value.first
|
58
|
+
else path
|
59
|
+
end
|
60
60
|
add_offense(node, message: MSG_ROUTE_TO) unless allowed_action?(action)
|
61
61
|
true
|
62
62
|
end
|
@@ -39,25 +39,25 @@ module RuboCop
|
|
39
39
|
return [node] if node.literal? || node.variable?
|
40
40
|
|
41
41
|
case node.type
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
42
|
+
when :begin
|
43
|
+
get_return_values(node.children.last)
|
44
|
+
when :block
|
45
|
+
get_return_values(node.body)
|
46
|
+
when :if
|
47
|
+
if_rets = get_return_values(node.if_branch)
|
48
|
+
else_rets = get_return_values(node.else_branch)
|
49
|
+
if_rets + else_rets
|
50
|
+
when :case
|
51
|
+
cases = []
|
52
|
+
node.each_when do |block|
|
53
|
+
cases += get_return_values(block.body)
|
54
|
+
end
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
cases + get_return_values(node.else_branch)
|
57
|
+
when :send
|
58
|
+
[node]
|
59
|
+
else
|
60
|
+
[]
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -5,10 +5,12 @@ require 'rubocop/cop/betterment/utils/parser'
|
|
5
5
|
require 'rubocop/cop/betterment/utils/method_return_table'
|
6
6
|
require 'rubocop/cop/betterment/utils/hardcoded_attribute'
|
7
7
|
require 'rubocop/cop/betterment/authorization_in_controller'
|
8
|
+
require 'rubocop/cop/betterment/direct_delayed_enqueue'
|
8
9
|
require 'rubocop/cop/betterment/dynamic_params'
|
9
10
|
require 'rubocop/cop/betterment/unscoped_find'
|
10
11
|
require 'rubocop/cop/betterment/unsafe_job'
|
11
12
|
require 'rubocop/cop/betterment/timeout'
|
13
|
+
require 'rubocop/cop/betterment/internals_protection'
|
12
14
|
require 'rubocop/cop/betterment/memoization_with_arguments'
|
13
15
|
require 'rubocop/cop/betterment/non_standard_actions'
|
14
16
|
require 'rubocop/cop/betterment/site_prism_loaded'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: betterlint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Development
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -108,10 +108,12 @@ files:
|
|
108
108
|
- lib/rubocop/cop/betterment/active_job_performable.rb
|
109
109
|
- lib/rubocop/cop/betterment/allowlist_blocklist.rb
|
110
110
|
- lib/rubocop/cop/betterment/authorization_in_controller.rb
|
111
|
+
- lib/rubocop/cop/betterment/direct_delayed_enqueue.rb
|
111
112
|
- lib/rubocop/cop/betterment/dynamic_params.rb
|
112
113
|
- lib/rubocop/cop/betterment/fetch_boolean.rb
|
113
114
|
- lib/rubocop/cop/betterment/hardcoded_id.rb
|
114
115
|
- lib/rubocop/cop/betterment/implicit_redirect_type.rb
|
116
|
+
- lib/rubocop/cop/betterment/internals_protection.rb
|
115
117
|
- lib/rubocop/cop/betterment/memoization_with_arguments.rb
|
116
118
|
- lib/rubocop/cop/betterment/non_standard_actions.rb
|
117
119
|
- lib/rubocop/cop/betterment/redirect_status.rb
|
@@ -132,10 +134,10 @@ licenses:
|
|
132
134
|
- MIT
|
133
135
|
metadata:
|
134
136
|
homepage_uri: https://github.com/Betterment/betterlint
|
135
|
-
source_code_uri: https://github.com/Betterment/betterlint/tree/v1.
|
136
|
-
changelog_uri: https://github.com/Betterment/betterlint/blob/v1.
|
137
|
+
source_code_uri: https://github.com/Betterment/betterlint/tree/v1.15.0
|
138
|
+
changelog_uri: https://github.com/Betterment/betterlint/blob/v1.15.0/CHANGELOG.md
|
137
139
|
bug_tracker_uri: https://github.com/Betterment/betterlint/issues
|
138
|
-
documentation_uri: https://www.rubydoc.info/gems/betterlint/1.
|
140
|
+
documentation_uri: https://www.rubydoc.info/gems/betterlint/1.15.0
|
139
141
|
rubygems_mfa_required: 'true'
|
140
142
|
post_install_message:
|
141
143
|
rdoc_options: []
|
@@ -152,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
154
|
- !ruby/object:Gem::Version
|
153
155
|
version: '0'
|
154
156
|
requirements: []
|
155
|
-
rubygems_version: 3.5.
|
157
|
+
rubygems_version: 3.5.21
|
156
158
|
signing_key:
|
157
159
|
specification_version: 4
|
158
160
|
summary: Betterment rubocop configuration
|