rubocop-gusto 10.0.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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +4 -0
  3. data/LICENSE +21 -0
  4. data/README.md +53 -0
  5. data/config/default.yml +781 -0
  6. data/config/rails.yml +122 -0
  7. data/exe/gusto-rubocop +12 -0
  8. data/exe/rubocop-gusto +9 -0
  9. data/lib/rubocop/cop/gusto/bootsnap_load_file.rb +57 -0
  10. data/lib/rubocop/cop/gusto/datadog_constant.rb +16 -0
  11. data/lib/rubocop/cop/gusto/execute_migration.rb +16 -0
  12. data/lib/rubocop/cop/gusto/factory_classes_or_modules.rb +19 -0
  13. data/lib/rubocop/cop/gusto/min_by_max_by.rb +45 -0
  14. data/lib/rubocop/cop/gusto/no_metaprogramming.rb +131 -0
  15. data/lib/rubocop/cop/gusto/no_rescue_error_message_checking.rb +66 -0
  16. data/lib/rubocop/cop/gusto/no_send.rb +32 -0
  17. data/lib/rubocop/cop/gusto/object_in.rb +36 -0
  18. data/lib/rubocop/cop/gusto/paperclip_or_attachable.rb +17 -0
  19. data/lib/rubocop/cop/gusto/perform_class_method.rb +73 -0
  20. data/lib/rubocop/cop/gusto/polymorphic_type_validation.rb +89 -0
  21. data/lib/rubocop/cop/gusto/prefer_process_last_status.rb +35 -0
  22. data/lib/rubocop/cop/gusto/rabl_extends.rb +43 -0
  23. data/lib/rubocop/cop/gusto/rails_env.rb +72 -0
  24. data/lib/rubocop/cop/gusto/rake_constants.rb +68 -0
  25. data/lib/rubocop/cop/gusto/regexp_bypass.rb +90 -0
  26. data/lib/rubocop/cop/gusto/sidekiq_params.rb +21 -0
  27. data/lib/rubocop/cop/gusto/toplevel_constants.rb +55 -0
  28. data/lib/rubocop/cop/gusto/use_paint_not_colorize.rb +240 -0
  29. data/lib/rubocop/cop/gusto/vcr_recordings.rb +49 -0
  30. data/lib/rubocop/cop/internal_affairs/assignment_first.rb +56 -0
  31. data/lib/rubocop/cop/internal_affairs/require_restrict_on_send.rb +62 -0
  32. data/lib/rubocop/gusto/cli.rb +22 -0
  33. data/lib/rubocop/gusto/config_yml.rb +135 -0
  34. data/lib/rubocop/gusto/init.rb +59 -0
  35. data/lib/rubocop/gusto/plugin.rb +29 -0
  36. data/lib/rubocop/gusto/templates/rubocop.yml +25 -0
  37. data/lib/rubocop/gusto/version.rb +7 -0
  38. data/lib/rubocop/gusto.rb +9 -0
  39. data/lib/rubocop-gusto.rb +13 -0
  40. metadata +178 -0
@@ -0,0 +1,240 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Gusto
6
+ # Requires the use of the `paint` gem for terminal color methods on strings
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # "string".cyan
12
+ # "string".red
13
+ # "string".green
14
+ # str = "hello"
15
+ # str.cyan
16
+ # "string".colorize(:blue)
17
+ # "string".colorize(:color => :blue)
18
+ # "string".colorize(:color => :blue, :background => :red)
19
+ # "string".blue.on_red
20
+ # "string".colorize(:blue).on_red
21
+ # "string".blue.underline
22
+ #
23
+ # # good
24
+ # "string"
25
+ #
26
+ # # if color is needed, use `paint` gem
27
+ # Paint["string", :cyan]
28
+ # Paint["string", :red]
29
+ # Paint["string", :green]
30
+ # Paint[str, :cyan]
31
+ # Paint["string", :blue]
32
+ # Paint["string", :blue, :red]
33
+ #
34
+ class UsePaintNotColorize < Base
35
+ extend AutoCorrector
36
+
37
+ # Common terminal color methods that should be prevented
38
+ COLOR_METHODS = Set.new(
39
+ %i(
40
+ black
41
+ red
42
+ green
43
+ yellow
44
+ blue
45
+ magenta
46
+ cyan
47
+ white
48
+ light_black
49
+ light_red
50
+ light_green
51
+ light_yellow
52
+ light_blue
53
+ light_magenta
54
+ light_cyan
55
+ light_white
56
+ colorize
57
+ on_black
58
+ on_red
59
+ on_green
60
+ on_yellow
61
+ on_blue
62
+ on_magenta
63
+ on_cyan
64
+ on_white
65
+ on_light_black
66
+ on_light_red
67
+ on_light_green
68
+ on_light_yellow
69
+ on_light_blue
70
+ on_light_magenta
71
+ on_light_cyan
72
+ on_light_white
73
+ bold
74
+ italic
75
+ underline
76
+ blink
77
+ swap
78
+ hide
79
+ uncolorize
80
+ )
81
+ ).freeze
82
+
83
+ # Style modifiers that are applied as additional options in Paint
84
+ STYLE_MODIFIERS = Set.new(
85
+ %i(
86
+ bold
87
+ italic
88
+ underline
89
+ blink
90
+ swap
91
+ hide
92
+ )
93
+ ).freeze
94
+
95
+ MSG = 'Use Paint instead of colorize for terminal colors.'
96
+ PROHIBITED_CLASS = 'String'
97
+ RESTRICT_ON_SEND = COLOR_METHODS
98
+
99
+ def on_send(node)
100
+ return unless node.receiver
101
+ return unless string_or_colorized_receiver?(node.receiver)
102
+
103
+ add_offense(node) do |corrector|
104
+ corrector.replace(node, correction(node))
105
+ end
106
+ end
107
+
108
+ def on_csend(node)
109
+ return unless string_or_colorized_receiver?(node.receiver)
110
+
111
+ add_offense(node) # no autocorrection for safe navigation due to chained calls
112
+ end
113
+
114
+ private
115
+
116
+ def string_or_colorized_receiver?(node)
117
+ string_receiver?(node) || colorized_string?(node)
118
+ end
119
+
120
+ def string_receiver?(node)
121
+ node.type?(:str, :dstr) || node.variable?
122
+ end
123
+
124
+ def colorized_string?(node)
125
+ node.send_type? &&
126
+ node.receiver.is_a?(RuboCop::AST::Node) &&
127
+ string_or_colorized_receiver?(node.receiver)
128
+ end
129
+
130
+ def correction(node)
131
+ # Find the original string and all color/style operations in the chain
132
+ original_string, color_ops = extract_string_and_operations(node)
133
+
134
+ foreground = nil
135
+ background = nil
136
+ styles = []
137
+
138
+ # Process all the operations to build the Paint parameters
139
+ color_ops.each do |op|
140
+ method_name = op[:method]
141
+ args = op[:args]
142
+
143
+ if method_name == :colorize
144
+ if args.length == 1 && args.first.sym_type?
145
+ # Single symbol argument, like colorize(:red)
146
+ foreground = ":#{args.first.value}"
147
+ elsif args.length == 1 && args.first.hash_type?
148
+ # Hash argument, like colorize(color: :red, background: :blue)
149
+ args.first.pairs.each do |pair|
150
+ break unless pair.value.sym_type? # can't handle non-symbol arguments
151
+
152
+ key = pair.key.value
153
+ value = ":#{pair.value.value}"
154
+
155
+ case key
156
+ when :color
157
+ foreground = value
158
+ when :background
159
+ background = value
160
+ when :mode
161
+ styles << value
162
+ else
163
+ break # unknown key, skip the rest of the hash
164
+ end
165
+ end
166
+ else
167
+ # if the argument is not a symbol or hash, we can't handle it
168
+ break
169
+ end
170
+ elsif method_name == :uncolorize
171
+ # If uncolorize is called, convert to Paint.unpaint
172
+ return "Paint.unpaint(#{original_string.source})"
173
+ elsif method_name.start_with?('on_')
174
+ # Background color
175
+ color_name = method_name.to_s.delete_prefix('on_')
176
+ background = ":#{color_name}"
177
+ elsif STYLE_MODIFIERS.include?(method_name)
178
+ # Style modifier
179
+ styles << ":#{method_name}"
180
+ elsif method_name.start_with?('light_')
181
+ # Light/bright foreground color
182
+ color = method_name.to_s.delete_prefix('light_')
183
+ foreground = ":bright, :#{color}"
184
+ else
185
+ # Regular foreground color
186
+ foreground = ":#{method_name}"
187
+ end
188
+ end
189
+
190
+ return unless foreground || background || styles.any?
191
+
192
+ # Build the Paint call
193
+ build_paint_call(original_string, foreground, background, styles)
194
+ end
195
+
196
+ def extract_string_and_operations(node)
197
+ operations = []
198
+ current = node
199
+
200
+ # Find the deepest operation in the chain
201
+ while current.send_type? && COLOR_METHODS.include?(current.method_name)
202
+ operations.unshift(
203
+ {
204
+ method: current.method_name,
205
+ args: current.arguments,
206
+ }
207
+ )
208
+
209
+ current = current.receiver
210
+ end
211
+
212
+ # The earliest receiver is the original string
213
+ [current, operations]
214
+ end
215
+
216
+ def build_paint_call(string_node, foreground, background, styles)
217
+ # Use string_content for string nodes, or source for variables and other expressions
218
+ string_expr = string_node.source
219
+
220
+ params = [string_expr]
221
+
222
+ # Add nil as a placeholder for foreground if we only have a background
223
+ if background && !foreground
224
+ params << 'nil'
225
+ elsif foreground
226
+ params << foreground
227
+ end
228
+
229
+ # Add background if present
230
+ params << background if background
231
+
232
+ # Add any style modifiers
233
+ params.concat(styles) unless styles.empty?
234
+
235
+ "Paint[#{params.join(', ')}]"
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Gusto
6
+ # Requires VCR to be set to not record in tests.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # vcr: {record: :all}
11
+ #
12
+ # # good
13
+ # vcr: {record: :none}
14
+ #
15
+ # @see https://github.com/vcr/vcr
16
+ #
17
+ class VcrRecordings < Base
18
+ extend AutoCorrector
19
+
20
+ MSG = 'VCR should be set to not record in tests. Please use vcr: {record: :none}.'
21
+
22
+ # @!method vcr_recording?(node)
23
+ def_node_matcher :vcr_recording?, <<~PATTERN
24
+ (pair (sym :record) (sym $_))
25
+ PATTERN
26
+
27
+ def on_pair(node)
28
+ return unless vcr_setting?(node)
29
+ return unless recording_enabled?(node.key.children.first, node.value.children.first)
30
+
31
+ add_offense(node) do |corrector|
32
+ replacement = node.source.sub(/: :\w*/, ': :none')
33
+ corrector.replace(node, replacement)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def vcr_setting?(node)
40
+ node.parent.parent.source.include?('vcr')
41
+ end
42
+
43
+ def recording_enabled?(option, value)
44
+ option == :record && value != :none
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Check for assignment as the first action in a cop hook.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # def on_send(node)
11
+ # foo = 1
12
+ # do_something
13
+ # end
14
+ #
15
+ # # good
16
+ # def on_send(node)
17
+ # do_something
18
+ # foo = 1
19
+ # end
20
+ #
21
+ class AssignmentFirst < Base
22
+ HOOKS = %i(
23
+ on_def
24
+ on_defs
25
+ on_send
26
+ on_csend
27
+ on_const
28
+ on_int
29
+ on_class
30
+ on_module
31
+ on_block
32
+ on_begin
33
+ on_kwbegin
34
+ after_int
35
+ after_def
36
+ after_send
37
+ after_csend
38
+ after_class
39
+ after_module
40
+ ).to_set.freeze
41
+ MSG = 'Avoid placing an assignment as the first action in `%{hook}`.'
42
+
43
+ def on_def(node)
44
+ return unless HOOKS.include?(node.method_name)
45
+ return unless node.body
46
+
47
+ # Look through a begin node, e.g. look inside parentheses
48
+ first_child = node.body.begin_type? ? node.body.children.first : node.body
49
+ return unless first_child&.assignment?
50
+
51
+ add_offense(first_child, message: format(MSG, hook: node.method_name))
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Check for missing `RESTRICT_ON_SEND`.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # class FooCop
11
+ # def on_send(node)
12
+ # # ...
13
+ # end
14
+ # end
15
+ #
16
+ # # good
17
+ # class FooCop
18
+ # RESTRICT_ON_SEND = %i[bad_method].freeze
19
+ # def on_send(node)
20
+ # # ...
21
+ # end
22
+ # end
23
+ #
24
+ # NOTE: This works for us because we do not write cops that investigate every send node.
25
+ # Upstream Rubocop chose not to implement this as there are many cops in Core that investigate every node.
26
+ class RequireRestrictOnSend < Base
27
+ MSG = 'Missing `RESTRICT_ON_SEND` declaration when using `on_send` or `after_send`.'
28
+
29
+ # @!method defined_send_callback?(node)
30
+ def_node_search :defined_send_callback?, <<~PATTERN
31
+ {
32
+ (def {:on_send :after_send} ...)
33
+ (alias (sym {:on_send :after_send}) _source ...)
34
+ (send nil? :alias_method {(sym {:on_send :after_send}) (str {"on_send" "after_send"})} _source ...)
35
+ }
36
+ PATTERN
37
+
38
+ # @!method restrict_on_send?(node)
39
+ def_node_search :restrict_on_send?, <<~PATTERN
40
+ (casgn nil? :RESTRICT_ON_SEND ...)
41
+ PATTERN
42
+
43
+ # from: https://github.com/rubocop/rubocop/blob/e78790e3c9e82f8e605009673a8d2eac40b18c4c/lib/rubocop/cop/internal_affairs/undefined_config.rb#L25
44
+ # @!method cop_class_def(node)
45
+ def_node_matcher :cop_class_def, <<~PATTERN
46
+ (class _
47
+ (const {nil? (const nil? :Cop) (const (const {cbase nil?} :RuboCop) :Cop)}
48
+ {:Base :Cop}) ...)
49
+ PATTERN
50
+
51
+ def on_class(node)
52
+ return if restrict_on_send?(node) # requirement met
53
+
54
+ return unless defined_send_callback?(node)
55
+ return unless cop_class_def(node)
56
+
57
+ add_offense(node)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+ require 'rubocop/gusto/config_yml'
5
+ require 'rubocop/gusto/init'
6
+
7
+ module RuboCop
8
+ module Gusto
9
+ class Cli < Thor
10
+ register(Init, 'init', 'init', 'Initialize rubocop-gusto and update .rubocop.yml')
11
+
12
+ desc 'sort [RUBOCOP_YML_PATH]', 'Sort the cops in a .rubocop.yml file (default: .rubocop.yml)'
13
+ method_option :output, type: :string, default: nil, desc: 'The path to the output file'
14
+ def sort(rubocop_yml_path = '.rubocop.yml')
15
+ say "Sorting #{rubocop_yml_path}..."
16
+ output_path = options[:output] || rubocop_yml_path
17
+ ConfigYml.load_file(rubocop_yml_path).sort!.write(output_path)
18
+ say "Done! #{output_path} sorted."
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+
5
+ module RuboCop
6
+ module Gusto
7
+ # A class for reading and writing a .rubocop.yml file.
8
+ #
9
+ # You may rightly ask why we don't just use the standard library's YAML.load_file
10
+ # and YAML.dump. Simple, we want to preserve the comments.
11
+ class ConfigYml
12
+ COMMENT_REGEX = /\A\s*#.*\z/
13
+ COP_HEADER_REGEX = /\A[A-Z0-9][A-Za-z0-9\/:]+:(\s*#.*)?\z/
14
+ KEY_REGEX = /\A\w[\w\/]+:(\s*#.*)?\z/i # case insensitive
15
+ PREAMBLE_KEYS = %w(inherit_mode inherit_gem inherit_from plugins require).freeze
16
+ INDENT_REGEX = /\A( |- )/
17
+
18
+ # @param [String] file_path the path to the .rubocop.yml file
19
+ def self.load_file(file_path = '.rubocop.yml')
20
+ new(File.readlines(file_path))
21
+ rescue Errno::ENOENT
22
+ new([])
23
+ end
24
+
25
+ attr_reader :preamble, :cops
26
+
27
+ # @param [Array<String>] lines the lines of the .rubocop.yml file
28
+ def initialize(lines)
29
+ @preamble, @cops = chunk_blocks(lines).partition do |block|
30
+ block.none? { |line| line.rstrip.match?(COP_HEADER_REGEX) }
31
+ end
32
+ end
33
+
34
+ # Find if there's already an inherit_gem section and add the gem to it if needed
35
+ def add_inherit_gem(gem_name, *config_paths)
36
+ update_section_data('inherit_gem') do |data|
37
+ data ||= {}
38
+ data[gem_name.to_s] = config_paths.flatten
39
+ data
40
+ end
41
+ end
42
+
43
+ # Add a plugin to the plugins section or create it if it doesn't exist
44
+ def add_plugin(plugins)
45
+ update_section_data('plugins') do |data|
46
+ data ||= []
47
+ data.concat(plugins).uniq
48
+ end
49
+ end
50
+
51
+ def update_section_data(section_name, &)
52
+ # Look for an existing section in the preamble
53
+ section = preamble.find { |chunk| chunk_name(chunk) == section_name }
54
+
55
+ if section
56
+ comments = section.select { |line| line.match?(COMMENT_REGEX) }
57
+ data = YAML.load(section.join)[section_name.to_s] # it can be present and nil
58
+ else
59
+ comments = []
60
+ data = nil
61
+ end
62
+
63
+ data = yield data
64
+
65
+ section_lines = YAML.dump({ section_name.to_s => data }).lines.drop(1) # drop the ---
66
+ section_lines.map! { |line| line.sub(/\A(\s*)-/, '\1 -') } # prefer indented lists
67
+ section_lines.insert(0, *comments) # add the comments back in at the top
68
+ section_lines << "\n" # ensure there's a trailing newline
69
+
70
+ section ? section.replace(section_lines) : preamble.unshift(section_lines)
71
+
72
+ self
73
+ end
74
+
75
+ def sort!
76
+ # Sort the preamble chunks by our preferred order, falling back to key name
77
+ preamble.sort_by! do |chunk|
78
+ key = chunk_name(chunk)
79
+ PREAMBLE_KEYS.index(key)&.to_s || key
80
+ end
81
+
82
+ # Sort the cops by their key name, putting comments at the top
83
+ cops.sort_by! { |cop| chunk_name(cop) || 'AAAAA/Comment?' }
84
+
85
+ self
86
+ end
87
+
88
+ def empty?
89
+ cops.empty? && preamble.empty?
90
+ end
91
+
92
+ def lines
93
+ combined = (preamble + cops).flatten
94
+ combined.pop # there's always one empty newline because of how we parse
95
+ combined
96
+ end
97
+
98
+ def to_s
99
+ lines.join
100
+ end
101
+
102
+ def write(file_path)
103
+ File.write(file_path, to_s)
104
+ end
105
+
106
+ private
107
+
108
+ # Return the name of a chunk by finding the root key
109
+ def chunk_name(chunk)
110
+ # Try to find a line that exactly matches KEY_REGEX
111
+ # Use rstrip, not strip, to preserve indentation
112
+ name_line = chunk.find { |line| line.rstrip.match?(KEY_REGEX) }
113
+ name_line&.rstrip&.delete_suffix(':')
114
+ end
115
+
116
+ # Splits the lines into blocks whenever we drop from indented to unindented
117
+ def chunk_blocks(lines)
118
+ # slice whenever we drop from indented to unindented
119
+ chunks = lines.slice_when do |prev, line|
120
+ prev.match?(INDENT_REGEX) && !prev.strip.empty? && !line.match?(INDENT_REGEX)
121
+ end
122
+
123
+ # Process each chunk to remove leading newlines and add 1 trailing newline
124
+ chunks.filter_map do |chunk|
125
+ # Remove leading and trailing empty lines
126
+ chunk.shift while chunk.first.to_s.strip.empty?
127
+ chunk.pop while chunk.last.to_s.strip.empty?
128
+
129
+ # Ensure each chunk ends with a blank newline
130
+ chunk << "\n"
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+ require 'yaml'
5
+ require 'rubocop/gusto/config_yml'
6
+
7
+ module RuboCop
8
+ module Gusto
9
+ class Init < Thor::Group
10
+ include Thor::Actions
11
+
12
+ PLUGINS = %w(rubocop-gusto rubocop-rspec rubocop-performance rubocop-rake rubocop-rails).freeze
13
+
14
+ class_option :rubocop_yml, type: :string, default: '.rubocop.yml'
15
+
16
+ def self.source_root
17
+ File.expand_path('templates', __dir__)
18
+ end
19
+
20
+ def add_dependencies
21
+ if rails?
22
+ # we don't want rubocop-rails to be a dependency of the gem so that we can use this in non-rails gems
23
+ run 'bundle show rubocop-rails >/dev/null || bundle add rubocop-rails --group development', capture: true
24
+ end
25
+
26
+ run 'bundle binstub rubocop', capture: true
27
+ end
28
+
29
+ def copy_config_files
30
+ config = ConfigYml.load_file(options[:rubocop_yml])
31
+
32
+ if config.empty?
33
+ template 'rubocop.yml', options[:rubocop_yml]
34
+ config = ConfigYml.load_file(options[:rubocop_yml])
35
+ end
36
+
37
+ if rails?
38
+ config.add_inherit_gem('rubocop-gusto', 'config/default.yml', 'config/rails.yml')
39
+ config.add_plugin(PLUGINS)
40
+ else
41
+ config.add_inherit_gem('rubocop-gusto', 'config/default.yml')
42
+ config.add_plugin(PLUGINS - %w(rubocop-rails))
43
+ end
44
+
45
+ config.sort!
46
+ config.write(options[:rubocop_yml])
47
+ say_status 'update', options[:rubocop_yml]
48
+
49
+ create_file('.rubocop_todo.yml', skip: true)
50
+ end
51
+
52
+ private
53
+
54
+ def rails?
55
+ File.exist?('config/application.rb')
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lint_roller'
4
+
5
+ module RuboCop
6
+ module Gusto
7
+ # A plugin that integrates Gusto's standard RuboCop cops and rules.
8
+ class Plugin < LintRoller::Plugin
9
+ def about
10
+ LintRoller::About.new(
11
+ name: 'rubocop-gusto',
12
+ version: RuboCop::Gusto::VERSION,
13
+ homepage: 'https://github.com/Gusto/rubocop-gusto',
14
+ description: "A collection of Gusto's standard RuboCop cops and rules."
15
+ )
16
+ end
17
+
18
+ def supported?(context)
19
+ context.engine == :rubocop
20
+ end
21
+
22
+ def rules(_context)
23
+ project_root = Pathname.new(__dir__).join('../../..')
24
+
25
+ LintRoller::Rules.new(type: :path, config_format: :rubocop, value: project_root.join('config', 'default.yml'))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ inherit_mode:
4
+ merge:
5
+ - Include
6
+
7
+ inherit_gem:
8
+ rubocop-gusto:
9
+ - config/default.yml
10
+
11
+ plugins:
12
+ - rubocop-gusto
13
+ - rubocop-rspec
14
+ - rubocop-performance
15
+ - rubocop-rake
16
+
17
+ AllCops:
18
+ NewCops: enable
19
+ TargetRubyVersion: 3.2
20
+
21
+ Layout/LineLength:
22
+ Enabled: false
23
+
24
+ Style/Documentation:
25
+ Enabled: false
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Gusto
5
+ VERSION = '10.0.0'
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'gusto/version'
4
+
5
+ module RuboCop
6
+ # RuboCop Gusto project namespace.
7
+ module Gusto
8
+ end
9
+ end