lib/rubocop/cop/layout/leading_comment_space.rb
# frozen_string_literal: true
module RuboCop
module Cop
module Layout
# Checks whether comments have a leading space after the
# `#` denoting the start of the comment. The leading space is not
# required for some RDoc special syntax, like `#++`, `#--`,
# `#:nodoc`, `=begin`- and `=end` comments, "shebang" directives,
# or rackup options.
#
# @example
#
# # bad
# #Some comment
#
# # good
# # Some comment
#
# @example AllowDoxygenCommentStyle: false (default)
#
# # bad
#
# #**
# # Some comment
# # Another line of comment
# #*
#
# @example AllowDoxygenCommentStyle: true
#
# # good
#
# #**
# # Some comment
# # Another line of comment
# #*
#
# @example AllowGemfileRubyComment: false (default)
#
# # bad
#
# #ruby=2.7.0
# #ruby-gemset=myproject
#
# @example AllowGemfileRubyComment: true
#
# # good
#
# #ruby=2.7.0
# #ruby-gemset=myproject
#
class LeadingCommentSpace < Base
include RangeHelp
extend AutoCorrector
MSG = 'Missing space after `#`.'
def on_new_investigation
processed_source.comments.each do |comment|
next unless /\A(?!#\+\+|#--)(#+[^#\s=])/.match?(comment.text)
next if comment.loc.line == 1 && allowed_on_first_line?(comment)
next if doxygen_comment_style?(comment)
next if gemfile_ruby_comment?(comment)
add_offense(comment) do |corrector|
expr = comment.source_range
corrector.insert_after(hash_mark(expr), ' ')
end
end
end
private
def hash_mark(expr)
range_between(expr.begin_pos, expr.begin_pos + 1)
end
def allowed_on_first_line?(comment)
shebang?(comment) || (rackup_config_file? && rackup_options?(comment))
end
def shebang?(comment)
comment.text.start_with?('#!')
end
def rackup_options?(comment)
comment.text.start_with?('#\\')
end
def rackup_config_file?
File.basename(processed_source.file_path).eql?('config.ru')
end
def allow_doxygen_comment?
cop_config['AllowDoxygenCommentStyle']
end
def doxygen_comment_style?(comment)
allow_doxygen_comment? && comment.text.start_with?('#*')
end
def allow_gemfile_ruby_comment?
cop_config['AllowGemfileRubyComment']
end
def gemfile?
File.basename(processed_source.file_path).eql?('Gemfile')
end
def ruby_comment_in_gemfile?(comment)
gemfile? && comment.text.start_with?('#ruby')
end
def gemfile_ruby_comment?(comment)
allow_gemfile_ruby_comment? && ruby_comment_in_gemfile?(comment)
end
end
end
end
end