rubocop-petal 1.3.0 → 1.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 +4 -4
- data/config/base.yml +2 -0
- data/config/default.yml +20 -6
- data/lib/rubocop/cop/rspec/aggregate_examples/language.rb +3 -1
- data/lib/rubocop/cop/sidekiq/const_argument.rb +60 -0
- data/lib/rubocop/cop/sidekiq/date_time_argument.rb +131 -0
- data/lib/rubocop/cop/sidekiq/helpers.rb +88 -0
- data/lib/rubocop/cop/sidekiq/keyword_arguments.rb +52 -0
- data/lib/rubocop/cop/sidekiq/symbol_argument.rb +31 -0
- data/lib/rubocop/petal/version.rb +1 -1
- data/lib/rubocop/petal.rb +1 -0
- metadata +8 -4
- data/lib/rubocop/cop/rspec/authenticated_as.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99a53e19d1caafc491f963ad3a723fb1b06f9e15fc9d0914db50287c68af1dd6
|
4
|
+
data.tar.gz: c1c37cbc85d3c4e56bdd2fffa928f8ce7f16db9afa5541014275a519d75146a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 862c765c3e4c638372c04b441d569d25b260f0333e887cb25b76064ac82214173e4367b0225e4023b9ee4de9f804bb57b224bc524fb4beec46b9eff4bde8546d
|
7
|
+
data.tar.gz: 263fe7fd0120e188d681dd68f7f44533e01c32d0a71596bc064781628175c7a40f0acea5cb22ec00707a8a67917fdb1dda1ee6811fea92ebf1047887346da20a
|
data/config/base.yml
CHANGED
data/config/default.yml
CHANGED
@@ -55,12 +55,6 @@ RSpec/AggregateExamples:
|
|
55
55
|
- validate_inclusion_of
|
56
56
|
- validates_exclusion_of
|
57
57
|
|
58
|
-
RSpec/AuthenticatedAs:
|
59
|
-
Description: 'Suggest to use authenticated_as instead of legacy api_key.'
|
60
|
-
Enabled: true
|
61
|
-
Include:
|
62
|
-
- spec/api/**/*_spec.rb
|
63
|
-
|
64
58
|
RSpec/CreateListMax:
|
65
59
|
Description: 'Prevent creating to most records with `FactoryBot.create_list`.'
|
66
60
|
Enabled: true
|
@@ -132,6 +126,26 @@ Performance/Snif:
|
|
132
126
|
Description: 'Prevent snif in favor of detect'
|
133
127
|
Enabled: true
|
134
128
|
|
129
|
+
Sidekiq/ConstArgument:
|
130
|
+
Description: "Prevent passing constant like Class as arguments in worker's perform method"
|
131
|
+
Enabled: true
|
132
|
+
|
133
|
+
Sidekiq/DateTimeArgument:
|
134
|
+
Description: "Prevent passing Date/Time arguments in worker's perform method"
|
135
|
+
Enabled: true
|
136
|
+
|
137
|
+
Sidekiq/KeywordArguments:
|
138
|
+
Description: "Prevent define keywords arguments in worker's perform method"
|
139
|
+
Enabled: true
|
140
|
+
Include:
|
141
|
+
- app/workers/**/*
|
142
|
+
|
135
143
|
Sidekiq/NoNilReturn:
|
136
144
|
Description: 'Prevent early nil return in workers'
|
137
145
|
Enabled: false
|
146
|
+
Include:
|
147
|
+
- app/workers/**/*
|
148
|
+
|
149
|
+
Sidekiq/SymbolArgument:
|
150
|
+
Description: "Prevent passing keywords arguments in worker's perform method"
|
151
|
+
Enabled: true
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helpers'
|
4
|
+
|
5
|
+
# credit: https://github.com/dvandersluis/rubocop-sidekiq/blob/master/lib/rubocop/cop/sidekiq/const_argument.rb
|
6
|
+
module RuboCop
|
7
|
+
module Cop
|
8
|
+
module Sidekiq
|
9
|
+
# This cop checks for Sidekiq worker perform arguments that look like classes or modules.
|
10
|
+
# These cannot be serialized for Redis, and should not be used with Sidekiq.
|
11
|
+
#
|
12
|
+
# Constants other than classes/modules are not flagged by this cop.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# # bad
|
16
|
+
# MyWorker.perform_async(MyClass)
|
17
|
+
# MyWorker.perform_async(MyModule)
|
18
|
+
# MyWorker.perform_async(Namespace::Class)
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# MyWorker.perform_async(MY_CONSTANT)
|
22
|
+
# MyWorker.perform_async(MyClass::MY_CONSTANT)
|
23
|
+
class ConstArgument < Base
|
24
|
+
CONSTANT_NAME = /\A[A-Z0-9_]+\z/.freeze
|
25
|
+
|
26
|
+
include Helpers
|
27
|
+
|
28
|
+
MSG = 'Objects are not Sidekiq-serializable.'
|
29
|
+
MSG_SELF = '`self` is not Sidekiq-serializable.'
|
30
|
+
|
31
|
+
def_node_matcher :initializer?, <<~PATTERN
|
32
|
+
(send const :new)
|
33
|
+
PATTERN
|
34
|
+
|
35
|
+
def_node_matcher :constant?, <<~PATTERN
|
36
|
+
(const _ _)
|
37
|
+
PATTERN
|
38
|
+
|
39
|
+
def_node_matcher :const_argument?, <<~PATTERN
|
40
|
+
{#initializer? #constant? self}
|
41
|
+
PATTERN
|
42
|
+
|
43
|
+
def on_send(node)
|
44
|
+
sidekiq_arguments(node).each do |arg|
|
45
|
+
next unless const_argument?(arg)
|
46
|
+
next if non_class_constant?(arg)
|
47
|
+
|
48
|
+
add_offense(arg, message: arg.self_type? ? MSG_SELF : MSG)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def non_class_constant?(arg)
|
55
|
+
arg.const_type? && arg.children[1].to_s.match?(CONSTANT_NAME)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helpers'
|
4
|
+
|
5
|
+
# credit: https://github.com/dvandersluis/rubocop-sidekiq/blob/master/lib/rubocop/cop/sidekiq/date_time_argument.rb
|
6
|
+
module RuboCop
|
7
|
+
module Cop
|
8
|
+
module Sidekiq
|
9
|
+
# This cop checks for date/time objects being passed as arguments to perform a Sidekiq
|
10
|
+
# worker. Dates, times, durations, and related classes cannot be serialized to Redis.
|
11
|
+
# Use an integer or string representation of the date/time instead.
|
12
|
+
#
|
13
|
+
# By default, this only allows `to_i` and `to_s` as valid, serializable methods for these
|
14
|
+
# classes. Use `AllowedMethods` to specify other allowed methods.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# # bad
|
18
|
+
# MyWorker.perform_async(Time.now)
|
19
|
+
# MyWorker.perform_async(Date.today)
|
20
|
+
# MyWorker.perform_async(DateTime.now)
|
21
|
+
# MyWorker.perform_async(ActiveSupport::TimeWithZone.new)
|
22
|
+
# MyWorker.perform_async(1.hour)
|
23
|
+
# MyWorker.perform_async(1.hour.ago)
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# MyWorker.perform_async(Time.now.to_i)
|
27
|
+
# MyWorker.perform_async(Date.today.to_s)
|
28
|
+
#
|
29
|
+
# @example AllowedMethods: [] (default)
|
30
|
+
# # bad
|
31
|
+
# MyWorker.perform_async(Time.now.mday)
|
32
|
+
#
|
33
|
+
# @example AllowedMethods: ['mday']
|
34
|
+
# # good
|
35
|
+
# MyWorker.perform_async(Time.now.mday)
|
36
|
+
#
|
37
|
+
class DateTimeArgument < ::RuboCop::Cop::Cop
|
38
|
+
DURATION_METHODS = %i[
|
39
|
+
second
|
40
|
+
seconds
|
41
|
+
minute
|
42
|
+
minutes
|
43
|
+
hour
|
44
|
+
hours
|
45
|
+
day
|
46
|
+
days
|
47
|
+
week
|
48
|
+
weeks
|
49
|
+
fortnight
|
50
|
+
fortnights
|
51
|
+
].freeze
|
52
|
+
|
53
|
+
DURATION_TO_TIME_METHODS = %i[
|
54
|
+
from_now
|
55
|
+
since
|
56
|
+
after
|
57
|
+
ago
|
58
|
+
until
|
59
|
+
before
|
60
|
+
].freeze
|
61
|
+
|
62
|
+
include Helpers
|
63
|
+
|
64
|
+
DURATION_MSG = 'Durations are not Sidekiq-serializable; use the integer instead.'
|
65
|
+
MSG = 'Date/Time objects are not Sidekiq-serializable; convert to integers or strings instead.'
|
66
|
+
ALLOWED_METHODS = %i[to_i to_s].freeze
|
67
|
+
|
68
|
+
def_node_matcher :rational_literal?, <<~PATTERN
|
69
|
+
(send
|
70
|
+
(int _) :/
|
71
|
+
(rational _))
|
72
|
+
PATTERN
|
73
|
+
|
74
|
+
def_node_matcher :duration?, <<~PATTERN
|
75
|
+
{
|
76
|
+
(send {int float rational #rational_literal?} #duration_method?)
|
77
|
+
(send (const (const _ :ActiveSupport) :Duration) ...)
|
78
|
+
}
|
79
|
+
PATTERN
|
80
|
+
|
81
|
+
def_node_matcher :date_time_send?, <<~PATTERN
|
82
|
+
$(send
|
83
|
+
`{
|
84
|
+
(const _ {:Date :DateTime :Time})
|
85
|
+
(const (const _ :ActiveSupport) :TimeWithZone)
|
86
|
+
}
|
87
|
+
...
|
88
|
+
)
|
89
|
+
PATTERN
|
90
|
+
|
91
|
+
def_node_matcher :date_time_arg?, <<~PATTERN
|
92
|
+
{ #duration? #date_time_send? (send `#duration? #duration_to_time_method?) }
|
93
|
+
PATTERN
|
94
|
+
|
95
|
+
def on_send(node)
|
96
|
+
sidekiq_arguments(node).each do |arg|
|
97
|
+
next unless date_time_arg?(arg)
|
98
|
+
next if node_approved?(arg)
|
99
|
+
|
100
|
+
# If the outer send (ie. the last method in the chain) is in the allowed method
|
101
|
+
# list, approve the node (so that sub chains aren't flagged).
|
102
|
+
if allowed_methods.include?(arg.method_name)
|
103
|
+
approve_node(arg)
|
104
|
+
next
|
105
|
+
end
|
106
|
+
|
107
|
+
add_offense(arg)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def allowed_methods
|
112
|
+
Array(cop_config['AllowedMethods']).concat(ALLOWED_METHODS).map(&:to_sym)
|
113
|
+
end
|
114
|
+
|
115
|
+
def duration_method?(sym)
|
116
|
+
DURATION_METHODS.include?(sym)
|
117
|
+
end
|
118
|
+
|
119
|
+
def duration_to_time_method?(sym)
|
120
|
+
DURATION_TO_TIME_METHODS.include?(sym)
|
121
|
+
end
|
122
|
+
|
123
|
+
def message(node)
|
124
|
+
return DURATION_MSG if duration?(node)
|
125
|
+
|
126
|
+
super
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# credit: https://github.com/dvandersluis/rubocop-sidekiq/blob/master/lib/rubocop/cop/helpers.rb
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Sidekiq
|
7
|
+
module Helpers
|
8
|
+
NODE_MATCHERS = lambda do
|
9
|
+
def_node_matcher :sidekiq_include?, <<~PATTERN
|
10
|
+
(send nil? :include (const (const nil? :Sidekiq) :Worker))
|
11
|
+
PATTERN
|
12
|
+
|
13
|
+
def_node_matcher :includes_sidekiq?, <<~PATTERN
|
14
|
+
{
|
15
|
+
(begin <#sidekiq_include? ...>)
|
16
|
+
#sidekiq_include?
|
17
|
+
}
|
18
|
+
PATTERN
|
19
|
+
|
20
|
+
def_node_matcher :worker_class_def?, <<~PATTERN
|
21
|
+
(class _ _ #includes_sidekiq?)
|
22
|
+
PATTERN
|
23
|
+
|
24
|
+
def_node_matcher :worker_anon_class_def?, <<~PATTERN
|
25
|
+
(block (send (const nil? :Class) :new ...) _ #includes_sidekiq?)
|
26
|
+
PATTERN
|
27
|
+
|
28
|
+
def_node_matcher :worker_class_application_worker?, <<~PATTERN
|
29
|
+
(class _ (const {nil? cbase} :ApplicationWorker) ...)
|
30
|
+
PATTERN
|
31
|
+
|
32
|
+
def_node_matcher :worker_anon_class_application_worker_def?, <<~PATTERN
|
33
|
+
(block (send (const nil? :Class) :new (const {nil? cbase} :ApplicationWorker)) ...)
|
34
|
+
PATTERN
|
35
|
+
|
36
|
+
def_node_matcher :sidekiq_worker?, <<~PATTERN
|
37
|
+
{#worker_class_def? #worker_anon_class_def? #worker_class_application_worker? #worker_anon_class_application_worker_def?}
|
38
|
+
PATTERN
|
39
|
+
|
40
|
+
def_node_matcher :sidekiq_perform?, <<~PATTERN
|
41
|
+
(send const ${:perform_async :perform_in :perform_at} ...)
|
42
|
+
PATTERN
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.included(klass)
|
46
|
+
klass.class_exec(&NODE_MATCHERS)
|
47
|
+
end
|
48
|
+
|
49
|
+
def in_sidekiq_worker?(node)
|
50
|
+
node.each_ancestor(:class, :block).detect { |anc| sidekiq_worker?(anc) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def sidekiq_arguments(node)
|
54
|
+
return [] unless node.send_type? && (method_name = sidekiq_perform?(node))
|
55
|
+
|
56
|
+
# Drop the first argument for perform_at and perform_in
|
57
|
+
expand_arguments(method_name == :perform_async ? node.arguments : node.arguments[1..])
|
58
|
+
end
|
59
|
+
|
60
|
+
def expand_arguments(arguments)
|
61
|
+
arguments.flat_map do |argument|
|
62
|
+
if argument.array_type? || argument.hash_type?
|
63
|
+
expand_arguments(argument.values)
|
64
|
+
else
|
65
|
+
argument
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def node_approved?(node)
|
71
|
+
@approved_nodes ||= []
|
72
|
+
@approved_nodes.any? { |r| within?(node.source_range, r) }
|
73
|
+
end
|
74
|
+
alias node_denied? node_approved?
|
75
|
+
|
76
|
+
def approve_node(node)
|
77
|
+
@approved_nodes ||= []
|
78
|
+
@approved_nodes << node.source_range
|
79
|
+
end
|
80
|
+
alias deny_node approve_node
|
81
|
+
|
82
|
+
def within?(inner, outer)
|
83
|
+
inner.begin_pos >= outer.begin_pos && inner.end_pos <= outer.end_pos
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helpers'
|
4
|
+
|
5
|
+
# credit: https://github.com/dvandersluis/rubocop-sidekiq/blob/master/lib/rubocop/cop/sidekiq/keyword_arguments.rb
|
6
|
+
module RuboCop
|
7
|
+
module Cop
|
8
|
+
module Sidekiq
|
9
|
+
# This cop checks for Sidekiq worker `perform` methods that use keyword args. Keyword args
|
10
|
+
# cannot be properly serialized to Redis and are thus not recommended. Use regular arguments
|
11
|
+
# instead.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # bad
|
15
|
+
# class MyWorker
|
16
|
+
# include Sidekiq::Worker
|
17
|
+
#
|
18
|
+
# def perform(id:, keyword_with_default: false, **other_kwargs)
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# class MyWorker
|
24
|
+
# include Sidekiq::Worker
|
25
|
+
#
|
26
|
+
# def perform(id, arg_with_default = false, *other_args)
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
class KeywordArguments < Base
|
30
|
+
include Helpers
|
31
|
+
|
32
|
+
MSG = "Keyword arguments are not allowed in a sidekiq worker's perform method."
|
33
|
+
KWARG_TYPES = %i[kwarg kwoptarg kwrestarg].freeze
|
34
|
+
|
35
|
+
def_node_matcher :perform_with_kwargs?, <<~PATTERN
|
36
|
+
(def :perform (args ... {kwarg kwoptarg kwrestarg}) ...)
|
37
|
+
PATTERN
|
38
|
+
|
39
|
+
def on_def(node)
|
40
|
+
return unless perform_with_kwargs?(node)
|
41
|
+
return unless in_sidekiq_worker?(node)
|
42
|
+
|
43
|
+
node.arguments.each do |arg|
|
44
|
+
next unless KWARG_TYPES.include?(arg.type)
|
45
|
+
|
46
|
+
add_offense(arg)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helpers'
|
4
|
+
|
5
|
+
# credit: https://github.com/dvandersluis/rubocop-sidekiq/blob/master/lib/rubocop/cop/sidekiq/symbol_argument.rb
|
6
|
+
module RuboCop
|
7
|
+
module Cop
|
8
|
+
module Sidekiq
|
9
|
+
# This cop checks for symbols passed as arguments to a Sidekiq worker's perform method.
|
10
|
+
# Symbols cannot be properly serialized for Redis and should be avoided. Use strings instead.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# # bad
|
14
|
+
# MyWorker.perform_async(:foo)
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# MyWorker.perform_async('foo')
|
18
|
+
class SymbolArgument < Base
|
19
|
+
include Helpers
|
20
|
+
|
21
|
+
MSG = 'Symbols are not Sidekiq-serializable; use strings instead.'
|
22
|
+
|
23
|
+
def on_send(node)
|
24
|
+
sidekiq_arguments(node).select(&:sym_type?).each do |argument|
|
25
|
+
add_offense(argument)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/rubocop/petal.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-petal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean-Francis Bastien
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -116,13 +116,17 @@ files:
|
|
116
116
|
- lib/rubocop/cop/rspec/aggregate_examples/matchers_with_side_effects.rb
|
117
117
|
- lib/rubocop/cop/rspec/aggregate_examples/metadata_helpers.rb
|
118
118
|
- lib/rubocop/cop/rspec/aggregate_examples/node_matchers.rb
|
119
|
-
- lib/rubocop/cop/rspec/authenticated_as.rb
|
120
119
|
- lib/rubocop/cop/rspec/create_list_max.rb
|
121
120
|
- lib/rubocop/cop/rspec/json_response.rb
|
122
121
|
- lib/rubocop/cop/rspec/multiple_expectations_auto_correct.rb
|
123
122
|
- lib/rubocop/cop/rspec/sidekiq_inline.rb
|
124
123
|
- lib/rubocop/cop/rspec/stub_products.rb
|
124
|
+
- lib/rubocop/cop/sidekiq/const_argument.rb
|
125
|
+
- lib/rubocop/cop/sidekiq/date_time_argument.rb
|
126
|
+
- lib/rubocop/cop/sidekiq/helpers.rb
|
127
|
+
- lib/rubocop/cop/sidekiq/keyword_arguments.rb
|
125
128
|
- lib/rubocop/cop/sidekiq/no_nil_return.rb
|
129
|
+
- lib/rubocop/cop/sidekiq/symbol_argument.rb
|
126
130
|
- lib/rubocop/petal.rb
|
127
131
|
- lib/rubocop/petal/inject.rb
|
128
132
|
- lib/rubocop/petal/version.rb
|
@@ -150,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
154
|
- !ruby/object:Gem::Version
|
151
155
|
version: '0'
|
152
156
|
requirements: []
|
153
|
-
rubygems_version: 3.4.
|
157
|
+
rubygems_version: 3.4.22
|
154
158
|
signing_key:
|
155
159
|
specification_version: 4
|
156
160
|
summary: Petal custom cops
|
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
module Cop
|
5
|
-
module RSpec
|
6
|
-
# Suggest to use authenticated_as instead of legacy api_key.
|
7
|
-
# It is faster, can be setup for multiple test.
|
8
|
-
#
|
9
|
-
# # bad
|
10
|
-
# get 'api/my_endpoint', headers: { HTTP_API_KEY: user.api_key }
|
11
|
-
#
|
12
|
-
# # good
|
13
|
-
# authenticated_as user
|
14
|
-
# get 'api/my_endpoint'
|
15
|
-
#
|
16
|
-
class AuthenticatedAs < Base
|
17
|
-
MSG = 'Use `authenticated_as` instead of legacy api_key.'
|
18
|
-
|
19
|
-
def_node_search :use_header_api_key, <<~PATTERN
|
20
|
-
(sym :HTTP_API_KEY)
|
21
|
-
PATTERN
|
22
|
-
|
23
|
-
def on_send(node)
|
24
|
-
api_key_usage = use_header_api_key(node).to_a.first
|
25
|
-
return unless api_key_usage
|
26
|
-
|
27
|
-
add_offense(api_key_usage)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|