<commit_before># frozen_string_literal: true

require 'yard'
require 'rubocop'

YARD::Rake::YardocTask.new(:yard_for_generate_documentation) do |task|
  task.files = ['lib/rubocop/cop/*/*.rb']
  task.options = ['--no-output']
end

desc 'Generate docs of all cops departments'
task generate_cops_documentation: :yard_for_generate_documentation do
  def cops_of_department(cops, department)
    cops.with_department(department).sort!
  end

  def cops_body(config, cop, description, examples_objects, pars)
    content = h2(cop.cop_name)
    content << properties(config, cop)
    content << "\n\n"
    content << "#{description}\n"
    content << examples(examples_objects) if examples_objects.count > 0
    content << default_settings(pars)
    content << references(config, cop)
    content
  end

  def examples(examples_object)
    content = h3('Example')
    content += examples_object.map { |e| code_example(e) }.join
    content
  end

  def properties(config, cop)
    content = "Enabled by default | Supports autocorrection\n".dup
    content << "--- | ---\n"
    enabled_by_default = config.for_cop(cop).fetch('Enabled')
    default_status = enabled_by_default ? 'Enabled' : 'Disabled'
    supports_autocorrect = cop.new.support_autocorrect? ? 'Yes' : 'No'
    content << "#{default_status} | #{supports_autocorrect}"
    content
  end

  def h2(title)
    content = "\n".dup
    content << "## #{title}\n"
    content << "\n"
    content
  end

  def h3(title)
    content = "\n".dup
    content << "### #{title}\n"
    content << "\n"
    content
  end

  def code_example(ruby_code)
    content = "```ruby\n".dup
    content << ruby_code.text.gsub('@good', '# good')
                        .gsub('@bad', '# bad').strip
    content << "\n```\n"
    content
  end

  def default_settings(pars)
    return '' unless pars.keys.count > 0
    content = h3('Important attributes')
    content << "Attribute | Value\n"
    content << "--- | ---\n"
    pars.each do |par|
      content << "#{par.first} |#{format_table_value(par.last)}\n"
    end
    content
  end

  def format_table_value(v)
    value = v.is_a?(Array) ? v.join(', ') : v.to_s
    value = value.gsub("#{Dir.pwd}/", '').gsub('*', '\*')
    " #{value}".rstrip
  end

  def references(config, cop)
    cop_config = config.for_cop(cop)
    urls = RuboCop::Cop::MessageAnnotator.new(config, cop_config, {}).urls
    return '' if urls.empty?

    content = h3('References')
    content << urls.map { |url| "* [#{url}](#{url})" }.join("\n")
    content << "\n"
    content
  end

  def print_cops_of_department(cops, department, config)
    selected_cops = cops_of_department(cops, department)
    content = "# #{department}\n".dup
    selected_cops.each do |cop|
      content << print_cop_with_doc(cop, config)<commit_msg>Improve configurable attributes section in the documentation<commit_after># frozen_string_literal: true

require 'yard'
require 'rubocop'

YARD::Rake::YardocTask.new(:yard_for_generate_documentation) do |task|
  task.files = ['lib/rubocop/cop/*/*.rb']
  task.options = ['--no-output']
end

desc 'Generate docs of all cops departments'
task generate_cops_documentation: :yard_for_generate_documentation do
  def cops_of_department(cops, department)
    cops.with_department(department).sort!
  end

  def cops_body(config, cop, description, examples_objects, pars)
    content = h2(cop.cop_name)
    content << properties(config, cop)
    content << "#{description}\n"
    content << examples(examples_objects) if examples_objects.count > 0
    content << configurations(pars)
    content << references(config, cop)
    content
  end

  def examples(examples_object)
    content = h3('Example')
    content += examples_object.map { |e| code_example(e) }.join
    content
  end

  def properties(config, cop)
    header = ['Enabled by default', 'Supports autocorrection']
    enabled_by_default = config.for_cop(cop).fetch('Enabled')
    content = [[
      enabled_by_default ? 'Enabled' : 'Disabled',
      cop.new.support_autocorrect? ? 'Yes' : 'No'
    ]]
    to_table(header, content) + "\n"
  end

  def h2(title)
    content = "\n".dup
    content << "## #{title}\n"
    content << "\n"
    content
  end

  def h3(title)
    content = "\n".dup
    content << "### #{title}\n"
    content << "\n"
    content
  end

  def code_example(ruby_code)
    content = "```ruby\n".dup
    content << ruby_code.text.gsub('@good', '# good')
                        .gsub('@bad', '# bad').strip
    content << "\n```\n"
    content
  end

  def configurations(pars)
    return '' if pars.empty?

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

    h3('Configurable attributes') + to_table(header, content)
  end

  # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
  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'
    else
      case pars[name]
      when String
        'String'
      when Integer
        'Integer'
      when true, false
        'Boolean'
      when Array
        'Array'
      else
        ''
      end
    end
  end
  # rubocop:enable Metrics/CyclomaticComplexity,Metrics/MethodLength

  def to_table(header, content)
    table = [
      header.join(' | '),
      Array.new(header.size, '---').join(' | ')
    ]
    table.concat(content.map { |c| c.join(' | ') })
    table.join("\n") + "\n"
  end

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

  def references(config, cop)
    cop_config = config.for_cop(cop)
    urls = RuboCop::Cop::MessageAnnotator.new(config, cop_config, {}).urls
    return '' if urls.empty?

    content = h3('References')
    content << urls.map { |url| "* [#{url}](#{url})" }.join("\n")
    content << "\n"
    content
  end

  def print_cops_of_department(cops, department, config)
    selected_cops = cops_of_department(cops, department)
    content = "# #{department}\n".dup
    selected_cops.each do |cop|
      content << print_cop_with_doc(cop, config)
{'fraction_non_alphanumeric': 0.14725407362703682, 'fraction_numerical': 0.002263126131563066, 'mean_word_length': 3.0743700061462813, 'pattern_counts': {'":': 0, '<': 72, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6486305', 'n_tokens_mistral': 2270, 'n_tokens_neox': 2194, 'n_words': 471}