123456789_123456789_123456789_123456789_123456789_

Class: CopsDocumentationGenerator Private

Do not use. This class is for internal use only.
Relationships & Source Files
Namespace Children
Classes:
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
Inherits: Object
Defined in: lib/rubocop/cops_documentation_generator.rb

Overview

Class for generating documentation of all cops departments

Constant Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

::RuboCop::Cop::Documentation - Included

Instance Attribute Details

#config (readonly, private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 60

attr_reader :departments, :cops, :config, :docs_path

#cops (readonly, private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 60

attr_reader :departments, :cops, :config, :docs_path

#departments (readonly, private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 60

attr_reader :departments, :cops, :config, :docs_path

#docs_path (readonly, private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 60

attr_reader :departments, :cops, :config, :docs_path

Instance Method Details

#call

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 49

def call
  YARD::Registry.load!
  departments.each { |department| print_cops_of_department(department) }

  print_table_of_contents
ensure
  RuboCop::ConfigLoader.default_configuration = nil
end

#check_examples_to_have_the_default_enforced_style!(example_objects, cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 77

def check_examples_to_have_the_default_enforced_style!(example_objects, cop)
  return if example_objects.none?

  examples_describing_enforced_style = example_objects.map(&:name).grep(/EnforcedStyle:/)
  return if examples_describing_enforced_style.none?

  if examples_describing_enforced_style.index { |name| name.match?('default') }.nonzero?
    raise "Put the example with the default EnforcedStyle on top for #{cop.cop_name}"
  end

  return if examples_describing_enforced_style.any? { |name| name.match?('default') }

  raise "Specify the default EnforcedStyle for #{cop.cop_name}"
end

#code_example(ruby_code) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 176

def code_example(ruby_code)
  content = +"[source,ruby]\n----\n"
  content << ruby_code.text.gsub('@good', '# good').gsub('@bad', '# bad').strip
  content << "\n----\n"
  content
end

#configurable_values(pars, name) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 209

def configurable_values(pars, name)
  case name
  when /^Enforced/
    supported_style_name = RuboCop::Cop::Util.to_supported_styles(name)
    format_table_value(pars[supported_style_name])
  when 'IndentationWidth'
    'Integer'
  when 'Database'
    format_table_value(pars['SupportedDatabases'])
  else
    case pars[name]
    when String
      'String'
    when Integer
      'Integer'
    when Float
      'Float'
    when true, false
      'Boolean'
    when Array
      'Array'
    else
      ''
    end
  end
end

#configuration_name(department, name) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 201

def configuration_name(department, name)
  return name unless name == 'AllowMultilineFinalElement'

  filename = "#{department_to_basename(department)}.adoc"
  "xref:#{filename}#allowmultilinefinalelement[AllowMultilineFinalElement]"
end

#configurations(department, pars, cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 183

def configurations(department, pars, cop)
  return '' if pars.empty?

  header = ['Name', 'Default value', 'Configurable values']
  configs = pars
            .each_key
            .reject { |key| key.start_with?('Supported') }
            .reject { |key| key.start_with?('AllowMultipleStyles') }
  content = configs.map do |name|
    configurable = configurable_values(pars, name)
    default = format_table_value(pars[name])

    [configuration_name(department, name), default, configurable]
  end

  cop_subsection('Configurable attributes', cop) + to_table(header, content)
end

#cop_code(cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 336

def cop_code(cop)
  YARD::Registry.all(:class).detect do |code_object|
    next unless RuboCop::Cop::Badge.for(code_object.to_s) == cop.badge

    yield code_object
  end
end

#cop_header(cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 153

def cop_header(cop)
  content = +"\n"
  content << "[##{to_anchor(cop.cop_name)}]\n"
  content << "== #{cop.cop_name}\n"
  content << "\n"
  content
end

#cop_status(status) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 376

def cop_status(status)
  return 'Disabled' unless status

  status == 'pending' ? 'Pending' : 'Enabled'
end

#cop_subsection(title, cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 161

def cop_subsection(title, cop)
  content = +"\n"
  content << "[##{to_anchor(title)}-#{to_anchor(cop.cop_name)}]\n"
  content << "=== #{title}\n"
  content << "\n"
  content
end

#cops_body(data) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 66

def cops_body(data)
  check_examples_to_have_the_default_enforced_style!(data.example_objects, data.cop)

  content = +''
  STRUCTURE.each do |section, block|
    content << instance_exec(data, &block)
    content << @extra_info[section].call(data) if @extra_info[section]
  end
  content
end

#cops_of_department(department) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 62

def cops_of_department(department)
  cops.with_department(department).sort!
end

#example_header(title, cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 169

def example_header(title, cop)
  content = +"[##{to_anchor(title)}-#{to_anchor(cop.cop_name)}]\n"
  content << "==== #{title}\n"
  content << "\n"
  content
end

#examples(example_objects, cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 92

def examples(example_objects, cop)
  return '' if example_objects.none?

  example_objects.each_with_object(cop_subsection('Examples', cop).dup) do |example, content|
    content << "\n" unless content.end_with?("\n\n")
    content << example_header(example.name, cop) unless example.name == ''
    content << code_example(example)
  end
end

#format_table_value(val) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 247

def format_table_value(val)
  value =
    case val
    when Array
      if val.empty?
        '`[]`'
      else
        val.map { |config| format_table_value(config) }.join(', ')
      end
    else
      wrap_backtick(val.nil? ? '<none>' : val)
    end
  value.gsub("#{@base_dir}/", '').rstrip
end

#properties(cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 129

def properties(cop)
  header = [
    'Enabled by default', 'Safe', 'Supports autocorrection', 'Version Added',
    'Version Changed'
  ]
  autocorrect = if cop.support_autocorrect?
                  context = cop.new.always_autocorrect? ? 'Always' : 'Command-line only'

                  "#{context}#{' (Unsafe)' unless cop.new(config).safe_autocorrect?}"
                else
                  'No'
                end
  cop_config = config.for_cop(cop)
  content = [[
    cop_status(cop_config.fetch('Enabled')),
    cop_config.fetch('Safe', true) ? 'Yes' : 'No',
    autocorrect,
    cop_config.fetch('VersionAdded', '-'),
    cop_config.fetch('VersionChanged', '-')
  ]]
  "#{to_table(header, content)}\n"
end

#references(cop, see_objects) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 271

def references(cop, see_objects) # rubocop:disable Metrics/AbcSize
  cop_config = config.for_cop(cop)
  urls = RuboCop::Cop::MessageAnnotator.new(config, cop.name, cop_config, {}).urls
  return '' if urls.empty? && see_objects.empty?

  content = cop_subsection('References', cop)
  content << urls.map { |url| "* #{url}" }.join("\n")
  content << "\n" unless urls.empty?
  content << see_objects.map { |see| "* #{see.name}" }.join("\n")
  content << "\n" unless see_objects.empty?
  content
end

#required_ruby_version(cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 114

def required_ruby_version(cop)
  return '' unless cop.respond_to?(:required_minimum_ruby_version)

  if cop.required_minimum_ruby_version
    requirement = cop.required_minimum_ruby_version
  elsif cop.required_maximum_ruby_version
    requirement = "<= #{cop.required_maximum_ruby_version}"
  else
    return ''
  end

  "NOTE: Requires Ruby version #{requirement}\n\n"
end

#safety_object(safety_objects, cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 102

def safety_object(safety_objects, cop)
  return '' if safety_objects.all? { |s| s.text.blank? }

  safety_objects.each_with_object(cop_subsection('Safety', cop).dup) do |safety_object, content|
    next if safety_object.text.blank?

    content << "\n" unless content.end_with?("\n\n")
    content << safety_object.text
    content << "\n"
  end
end

#table_contents (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 372

def table_contents
  departments.map { |department| table_of_content_for_department(department) }.join("\n")
end

#table_of_content_for_department(department) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 344

def table_of_content_for_department(department)
  type_title = department[0].upcase + department[1..]
  filename = "#{department_to_basename(department)}.adoc"
  content = +"=== Department xref:#{filename}[#{type_title}]\n\n"
  cops_of_department(department).each do |cop|
    anchor = to_anchor(cop.cop_name)
    content << "* xref:#{filename}##{anchor}[#{cop.cop_name}]\n"
  end

  content
end

#to_anchor(title) (private)

HTML anchor are somewhat limited in what characters they can contain, just accept a known-good subset. As long as it’s consistent it doesn’t matter.

Style/AccessModifierDeclarations ⇒ styleaccessmodifierdeclarations OnlyFor: [] (default) ⇒ onlyfor_-_-_default

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 387

def to_anchor(title)
  title.delete('/').tr(' ', '-').gsub(/[^a-zA-Z0-9-]/, '_').downcase
end

#to_table(header, content) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 237

def to_table(header, content)
  table = ['|===', "| #{header.join(' | ')}\n\n"].join("\n")
  marked_contents = content.map do |plain_content|
    # Escape `|` with backslash to prevent the regexp `|` is not used as a table separator.
    plain_content.map { |c| "| #{c.gsub('|', '\|')}" }.join("\n")
  end
  table << marked_contents.join("\n\n")
  table << "\n|===\n"
end

#wrap_backtick(value) (private)

[ GitHub ]

  
# File 'lib/rubocop/cops_documentation_generator.rb', line 262

def wrap_backtick(value)
  if value.is_a?(String)
    # Use `+` to prevent text like `**/*.gemspec`, `spec/**/*` from being bold.
    value.include?('*') ? "`+#{value}+`" : "`#{value}`"
  else
    "`#{value}`"
  end
end