class RuboCop::Cop::Generator

Source and spec generator for new cops

This generator will take a cop name and generate a source file and spec file when given a valid qualified cop name.

Constants

CONFIGURATION_ADDED_MESSAGE
SOURCE_TEMPLATE

Note: RDoc 5.1.0 or lower has the following issue. github.com/rubocop-hq/rubocop/issues/7043

The following `String#strip_indent` can be replaced with squiggly heredoc when RuboCop supports Ruby 2.5 or higher (RDoc 6.0 or higher).

SPEC_TEMPLATE

Attributes

badge[R]
github_user[R]
output[R]

Public Class Methods

new(name, github_user, output: $stdout) click to toggle source
# File lib/rubocop/cop/generator.rb, line 112
def initialize(name, github_user, output: $stdout)
  @badge = Badge.parse(name)
  @github_user = github_user
  @output = output
  return if badge.qualified?

  raise ArgumentError, 'Specify a cop name with Department/Name style'
end

Public Instance Methods

inject_config(config_file_path: 'config/default.yml') click to toggle source
# File lib/rubocop/cop/generator.rb, line 136
def inject_config(config_file_path: 'config/default.yml')
  injector =
    ConfigurationInjector.new(configuration_file_path: config_file_path,
                              badge: badge,
                              version_added: bump_minor_version)

  injector.inject do
    output.puts(format(CONFIGURATION_ADDED_MESSAGE,
                       configuration_file_path: config_file_path))
  end
end
inject_require(root_file_path: 'lib/rubocop.rb') click to toggle source
# File lib/rubocop/cop/generator.rb, line 129
def inject_require(root_file_path: 'lib/rubocop.rb')
  RequireFileInjector.new(
    source_path: source_path,
    root_file_path: root_file_path
  ).inject
end
todo() click to toggle source
# File lib/rubocop/cop/generator.rb, line 148
      def todo
        <<~TODO
          Do 3 steps:
            1. Add an entry to the "New features" section in CHANGELOG.md,
               e.g. "Add new `#{badge}` cop. ([@#{github_user}][])"
            2. Modify the description of #{badge} in config/default.yml
            3. Implement your new cop in the generated file!
        TODO
      end
write_source() click to toggle source
# File lib/rubocop/cop/generator.rb, line 121
def write_source
  write_unless_file_exists(source_path, generated_source)
end
write_spec() click to toggle source
# File lib/rubocop/cop/generator.rb, line 125
def write_spec
  write_unless_file_exists(spec_path, generated_spec)
end

Private Instance Methods

bump_minor_version() click to toggle source
# File lib/rubocop/cop/generator.rb, line 216
def bump_minor_version
  versions = RuboCop::Version::STRING.split('.')

  "#{versions[0]}.#{versions[1].succ}"
end
generate(template) click to toggle source
# File lib/rubocop/cop/generator.rb, line 183
def generate(template)
  format(template, department: badge.department, cop_name: badge.cop_name)
end
generated_source() click to toggle source
# File lib/rubocop/cop/generator.rb, line 175
def generated_source
  generate(SOURCE_TEMPLATE)
end
generated_spec() click to toggle source
# File lib/rubocop/cop/generator.rb, line 179
def generated_spec
  generate(SPEC_TEMPLATE)
end
snake_case(camel_case_string) click to toggle source
# File lib/rubocop/cop/generator.rb, line 207
def snake_case(camel_case_string)
  return 'rspec' if camel_case_string == 'RSpec'

  camel_case_string
    .gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
    .gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2')
    .downcase
end
source_path() click to toggle source
# File lib/rubocop/cop/generator.rb, line 197
def source_path
  File.join(
    'lib',
    'rubocop',
    'cop',
    snake_case(badge.department.to_s),
    "#{snake_case(badge.cop_name.to_s)}.rb"
  )
end
spec_path() click to toggle source
# File lib/rubocop/cop/generator.rb, line 187
def spec_path
  File.join(
    'spec',
    'rubocop',
    'cop',
    snake_case(badge.department.to_s),
    "#{snake_case(badge.cop_name.to_s)}_spec.rb"
  )
end
write_unless_file_exists(path, contents) click to toggle source
# File lib/rubocop/cop/generator.rb, line 162
def write_unless_file_exists(path, contents)
  if File.exist?(path)
    warn "rake new_cop: #{path} already exists!"
    exit!
  end

  dir = File.dirname(path)
  FileUtils.mkdir_p(dir) unless File.exist?(dir)

  File.write(path, contents)
  output.puts "[create] #{path}"
end