Class: RuboCop::Cop::Generator Private
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Inherits: | Object |
Defined in: | lib/rubocop/cop/generator.rb, lib/rubocop/cop/generator/configuration_injector.rb, lib/rubocop/cop/generator/require_file_injector.rb |
Overview
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.
Constant Summary
-
CONFIGURATION_ADDED_MESSAGE =
Internal use only
# File 'lib/rubocop/cop/generator.rb', line 115'[modify] A configuration for the cop is added into ' \ '%<configuration_file_path>s.'
-
SOURCE_TEMPLATE =
Internal use only
# File 'lib/rubocop/cop/generator.rb', line 11<<~RUBY # frozen_string_literal: true module RuboCop module Cop module %<department>s # TODO: Write cop description and example of bad / good code. For every # `SupportedStyle` and unique configuration, there needs to be examples. # Examples must have valid Ruby syntax. Do not use upticks. # # @safety # Delete this section if the cop is not unsafe (`Safe: false` or # `SafeAutoCorrect: false`), or use it to explain how the cop is # unsafe. # # @example EnforcedStyle: bar (default) # # Description of the `bar` style. # # # bad # bad_bar_method # # # bad # bad_bar_method(args) # # # good # good_bar_method # # # good # good_bar_method(args) # # @example EnforcedStyle: foo # # Description of the `foo` style. # # # bad # bad_foo_method # # # bad # bad_foo_method(args) # # # good # good_foo_method # # # good # good_foo_method(args) # class %<cop_name>s < Base # TODO: Implement the cop in here. # # In many cases, you can use a node matcher for matching node pattern. # See https://github.com/rubocop/rubocop-ast/blob/master/lib/rubocop/ast/node_pattern.rb # # For example MSG = 'Use `#good_method` instead of `#bad_method`.' # TODO: Don't call `on_send` unless the method name is in this list # If you don't need `on_send` in the cop you created, remove it. RESTRICT_ON_SEND = %%i[bad_method].freeze # @!method bad_method?(node) def_node_matcher :bad_method?, <<~PATTERN (send nil? :bad_method ...) PATTERN # Called on every `send` node (method call) while walking the AST. # TODO: remove this method if inspecting `send` nodes is unneeded for your cop. # By default, this is aliased to `on_csend` as well to handle method calls # with safe navigation, remove the alias if this is unnecessary. # If kept, ensure your tests cover safe navigation as well! def on_send(node) return unless bad_method?(node) add_offense(node) end alias on_csend on_send end end end end RUBY
-
SPEC_TEMPLATE =
Internal use only
# File 'lib/rubocop/cop/generator.rb', line 91<<~SPEC # frozen_string_literal: true RSpec.describe RuboCop::Cop::%<department>s::%<cop_name>s, :config do let(:config) { RuboCop::Config.new } # TODO: Write test code # # For example it 'registers an offense when using `#bad_method`' do expect_offense(<<~RUBY) bad_method ^^^^^^^^^^ Use `#good_method` instead of `#bad_method`. RUBY end it 'does not register an offense when using `#good_method`' do expect_no_offenses(<<~RUBY) good_method RUBY end end SPEC
Class Method Summary
- .new(name, output: $stdout) ⇒ Generator constructor Internal use only Internal use only
Instance Attribute Summary
Instance Method Summary
- #inject_config(config_file_path: 'config/default.yml', version_added: '<<next>>') Internal use only Internal use only
- #inject_require(root_file_path: 'lib/rubocop.rb') Internal use only Internal use only
- #todo Internal use only Internal use only
- #write_source Internal use only Internal use only
- #write_spec Internal use only Internal use only
- #generate(template) private Internal use only Internal use only
- #generated_source private Internal use only Internal use only
- #generated_spec private Internal use only Internal use only
- #snake_case(camel_case_string) private Internal use only Internal use only
- #source_path private Internal use only Internal use only
- #spec_path private Internal use only Internal use only
- #write_unless_file_exists(path, contents) private Internal use only Internal use only
Instance Attribute Details
#badge (readonly, private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 166
attr_reader :badge, :output
#output (readonly, private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 166
attr_reader :badge, :output
Instance Method Details
#generate(template) (private)
This method is for internal use only.
[ GitHub ]
#generated_source (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 181
def generated_source generate(SOURCE_TEMPLATE) end
#generated_spec (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 185
def generated_spec generate(SPEC_TEMPLATE) end
#inject_config(config_file_path: 'config/default.yml', version_added: '<<next>>')
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 139
def inject_config(config_file_path: 'config/default.yml', version_added: '<<next>>') injector = ConfigurationInjector.new(configuration_file_path: config_file_path, badge: badge, version_added: version_added) injector.inject do # rubocop:disable Lint/UnexpectedBlockArity output.puts(format(CONFIGURATION_ADDED_MESSAGE, configuration_file_path: config_file_path)) end end
#inject_require(root_file_path: 'lib/rubocop.rb')
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 135
def inject_require(root_file_path: 'lib/rubocop.rb') RequireFileInjector.new(source_path: source_path, root_file_path: root_file_path).inject end
#snake_case(camel_case_string) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 214
def snake_case(camel_case_string) camel_case_string .gsub('RSpec', 'Rspec') .gsub(%r{([^A-Z/])([A-Z]+)}, '\1_\2') .gsub(%r{([A-Z])([A-Z][^A-Z\d/]+)}, '\1_\2') .downcase end
#source_path (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 204
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 (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 194
def spec_path File.join( 'spec', 'rubocop', 'cop', snake_case(badge.department.to_s), "#{snake_case(badge.cop_name.to_s)}_spec.rb" ) end
#todo
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 152
def todo <<~TODO Do 4 steps: 1. Modify the description of #{badge} in config/default.yml 2. Implement your new cop in the generated file! 3. Commit your new cop with a message such as e.g. "Add new `#{badge}` cop" 4. Run `bundle exec rake changelog:new` to generate a changelog entry for your new cop. TODO end
#write_source
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 127
def write_source write_unless_file_exists(source_path, generated_source) end
#write_spec
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 131
def write_spec write_unless_file_exists(spec_path, generated_spec) end
#write_unless_file_exists(path, contents) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/generator.rb', line 168
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) File.write(path, contents) output.puts "[create] #{path}" end