lib/rubocop/cop/message_annotator.rb
# frozen_string_literal: true
module RuboCop
module Cop
# Message Annotator class annotates a basic offense message
# based on params passed into initializer.
#
# @see #initialize
#
# @example
# RuboCop::Cop::MessageAnnotator.new(
# config, cop_name, cop_config, @options
# ).annotate('message')
# #=> 'Cop/CopName: message (http://example.org/styleguide)'
class MessageAnnotator
attr_reader :options, :config, :cop_name, :cop_config
@style_guide_urls = {}
class << self
attr_reader :style_guide_urls
end
# @param config [RuboCop::Config] Check configs for all cops
# @note Message Annotator specifically checks the
# following config options for_all_cops
# :StyleGuideBaseURL [String] URL for styleguide
# :DisplayStyleGuide [Boolean] Include styleguide and reference URLs
# :ExtraDetails [Boolean] Include cop details
# :DisplayCopNames [Boolean] Include cop name
#
# @param [String] cop_name for specific cop name
# @param [Hash] cop_config configs for specific cop, from config#for_cop
# @option cop_config [String] :StyleGuide Extension of base styleguide URL
# @option cop_config [String] :Reference Full reference URL
# @option cop_config [String] :Details
#
# @param [Hash, nil] options optional
# @option options [Boolean] :display_style_guide
# Include style guide and reference URLs
# @option options [Boolean] :extra_details
# Include cop specific details
# @option options [Boolean] :debug
# Include debug output
# @option options [Boolean] :display_cop_names
# Include cop name
def initialize(config, cop_name, cop_config, options)
@config = config
@cop_name = cop_name
@cop_config = cop_config || {}
@options = options
end
# Returns the annotated message,
# based on params passed into initializer
#
# @return [String] annotated message
def annotate(message)
message = "#{cop_name}: #{message}" if display_cop_names?
message += " #{details}" if extra_details? && details
if display_style_guide?
links = urls.join(', ')
message = "#{message} (#{links})"
end
message
end
def urls
[style_guide_url, *reference_urls].compact
end
private
def style_guide_url
url = cop_config['StyleGuide']
return nil if url.nil? || url.empty?
self.class.style_guide_urls[url] ||= begin
base_url = style_guide_base_url
if base_url.nil? || base_url.empty?
url
else
URI.join(base_url, url).to_s
end
end
end
# Returns the base style guide URL from AllCops or the specific department
#
# @return [String] style guide URL
def style_guide_base_url
department_name = cop_name.split('/')[0..-2].join('/')
config.for_department(department_name)['StyleGuideBaseURL'] ||
config.for_all_cops['StyleGuideBaseURL']
end
def display_style_guide?
(options[:display_style_guide] || config.for_all_cops['DisplayStyleGuide']) && !urls.empty?
end
def reference_urls
urls = Array(cop_config['Reference'])
urls.nil? || urls.empty? ? nil : urls.reject(&:empty?)
end
def extra_details?
options[:extra_details] || config.for_all_cops['ExtraDetails']
end
def debug?
options[:debug]
end
def display_cop_names?
return true if debug?
return false if options[:display_cop_names] == false
return true if options[:display_cop_names]
return false if options[:format] == 'json'
config.for_all_cops['DisplayCopNames']
end
def details
details = cop_config && cop_config['Details']
details.nil? || details.empty? ? nil : details
end
end
end
end