123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::DirectiveComment

Relationships & Source Files
Inherits: Object
Defined in: lib/rubocop/directive_comment.rb

Overview

This class wraps the Parser::Source::Comment object that represents a special rubocop:disable and rubocop:enable comment and exposes what cops it contains.

Constant Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(comment, cop_registry = Cop::Registry.global) ⇒ DirectiveComment

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 58

def initialize(comment, cop_registry = Cop::Registry.global)
  @comment = comment
  @cop_registry = cop_registry
  match_data = comment.text.match(DIRECTIVE_COMMENT_REGEXP)
  @match_data = match_data&.pre_match&.match?(/\A#\s*\z/) ? nil : match_data
  @mode, @cops = match_captures
end

Class Method Details

.before_comment(line)

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 52

def self.before_comment(line)
  line.split(DIRECTIVE_COMMENT_REGEXP).first
end

Instance Attribute Details

#all_cops?Boolean (readonly)

Checks if all cops specified in this directive

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 182

def all_cops?
  cops == 'all'
end

#comment (readonly)

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 56

attr_reader :comment, :cop_registry, :mode, :cops

#cop_registry (readonly)

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 56

attr_reader :comment, :cop_registry, :mode, :cops

#cops (readonly)

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 56

attr_reader :comment, :cop_registry, :mode, :cops

#disable_next?Boolean (readonly)

Checks if this directive disables cops for the next statement only

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 147

def disable_next?
  %w[disable-next todo-next].include?(mode)
end

#disabled?Boolean (readonly)

Checks if this directive disables cops

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 142

def disabled?
  %w[disable todo].include?(mode) || disable_next?
end

#disabled_all?Boolean (readonly)

Checks if this directive disables all cops

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 177

def disabled_all?
  disabled? && all_cops?
end

#enabled?Boolean (readonly)

Checks if this directive enables cops

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 152

def enabled?
  mode == 'enable'
end

#enabled_all?Boolean (readonly)

Checks if this directive enables all cops

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 172

def enabled_all?
  !disabled? && all_cops?
end

#malformed?Boolean (readonly)

Checks if the comment is malformed as a # rubocop: directive

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 72

def malformed?
  return true if !start_with_marker? || @match_data.nil?
  return true if missing_cop_name?

  tail = @match_data.post_match.lstrip
  !(tail.empty? || tail.start_with?(TRAILING_COMMENT_MARKER))
end

#missing_cop_name?Boolean (readonly)

Checks if the directive comment is missing a cop name

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 81

def missing_cop_name?
  return false if push? || pop?

  MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP.match?(comment.text)
end

#mode (readonly)

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 56

attr_reader :comment, :cop_registry, :mode, :cops

#pop?Boolean (readonly)

Checks if this directive is a pop

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 162

def pop?
  mode == 'pop'
end

#push?Boolean (readonly)

Checks if this directive is a push

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 157

def push?
  mode == 'push'
end

#single_line?Boolean (readonly)

Checks if this directive relates to single line

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 100

def single_line?
  !comment.text.start_with?(DIRECTIVE_COMMENT_REGEXP)
end

#start_with_marker?Boolean (readonly)

Checks if the comment starts with # rubocop: marker

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 67

def start_with_marker?
  comment.text.start_with?(DIRECTIVE_MARKER_REGEXP)
end

Instance Method Details

#all_cop_names (private)

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 234

def all_cop_names
  exclude_lint_department_cops(cop_registry.names)
end

#cop_names

Returns array of specified in this directive cop names

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 187

def cop_names
  @cop_names ||= all_cops? ? all_cop_names : parsed_cop_names
end

#cop_names_for_department(department) (private)

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 238

def cop_names_for_department(department)
  names = cop_registry.names_for_department(department)
  department == LINT_DEPARTMENT ? exclude_lint_department_cops(names) : names
end

#department?(name) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 230

def department?(name)
  cop_registry.department?(name)
end

#department_names

Returns array of specified in this directive department names when all department disabled

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 198

def department_names
  raw_cop_names.select { |cop| department?(cop) }
end

#directive_count

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 212

def directive_count
  raw_cop_names.count
end

#exclude_lint_department_cops(cops) (private)

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 243

def exclude_lint_department_cops(cops)
  cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP]
end

#in_directive_department?(cop) ⇒ Boolean

Checks if directive departments include cop

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 203

def in_directive_department?(cop)
  department_names.any? { |department| cop.start_with?(department) }
end

#line_number

Returns line number for directive

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 217

def line_number
  comment.source_range.line
end

#match?(cop_names) ⇒ Boolean

Checks if this directive contains all the given cop names

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 105

def match?(cop_names)
  parsed_cop_names.uniq.sort == cop_names.uniq.sort
end

#match_captures

Returns match captures to directive comment pattern

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 131

def match_captures
  @match_captures ||= @match_data && begin
    captures = @match_data.captures
    mode = captures[0]
    # COPS_PATTERN is at captures[1], PUSH_POP_ARGS_PATTERN is at captures[4]
    cops = captures[1] || captures[4]
    [mode, cops]
  end
end

#overridden_by_department?(cop) ⇒ Boolean

Checks if cop department has already used in directive comment

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 208

def overridden_by_department?(cop)
  in_directive_department?(cop) && raw_cop_names.include?(cop)
end

#parse_push_args (private)

[ GitHub ]

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

def parse_push_args
  return {} unless push? && cops

  args = {}
  cops.split.each do |cop_spec|
    op = cop_spec[0]
    cop_name = cop_spec[1..]
    args[op] ||= []
    args[op] << cop_name
  end
  args
end

#parsed_cop_names (private)

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 223

def parsed_cop_names
  cops = raw_cop_names.map do |name|
    department?(name) ? cop_names_for_department(name) : name
  end.flatten
  cops - [LINT_SYNTAX_COP]
end

#push_args

Returns the push arguments as a hash of cop names with their operations

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 167

def push_args
  @push_args ||= parse_push_args
end

#range

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 109

def range
  match = comment.text.match(DIRECTIVE_COMMENT_REGEXP)
  begin_pos = comment.source_range.begin_pos
  Parser::Source::Range.new(
    comment.source_range.source_buffer, begin_pos + match.begin(0), begin_pos + match.end(0)
  )
end

#range_with_reason

#range stops at the cop list, so a -- reason sits outside it. The reason documents the directive and means nothing once the directive is gone, so removal has to cover both. Any other trailing text is an ordinary comment and is left alone.

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 120

def range_with_reason
  directive_range = range
  trailing = Parser::Source::Range.new(
    comment.source_range.source_buffer, directive_range.end_pos, comment.source_range.end_pos
  )
  return directive_range unless trailing.source.lstrip.start_with?(TRAILING_COMMENT_MARKER)

  directive_range.with(end_pos: comment.source_range.end_pos)
end

#raw_cop_names

Returns an array of cops for this directive comment, without resolving departments

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 192

def raw_cop_names
  @raw_cop_names ||= (cops || '').split(/,\s*/)
end

#reason

The text of the directive’s optional -- trailing comment, or nil when there is none.

[ GitHub ]

  
# File 'lib/rubocop/directive_comment.rb', line 89

def reason
  return unless @match_data

  tail = @match_data.post_match.lstrip
  return unless tail.start_with?(TRAILING_COMMENT_MARKER)

  reason = tail.delete_prefix(TRAILING_COMMENT_MARKER).strip
  reason unless reason.empty?
end