123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::Cop::Style::MagicCommentFormat

Relationships & Source Files
Namespace Children
Classes:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, ::RuboCop::Cop::AutoCorrector, ::RuboCop::Cop::Base, ::RuboCop::ExcludeLimit, NodePattern::Macros, RuboCop::AST::Sexp
Instance Chain:
Inherits: RuboCop::Cop::Base
Defined in: lib/rubocop/cop/style/magic_comment_format.rb

Overview

Ensures magic comments are written consistently throughout your code base. Looks for discrepancies in separators (- vs _) and capitalization for both magic comment directives and values.

Required capitalization can be set with the DirectiveCapitalization and ValueCapitalization configuration keys.

Note
If one of these configuration is set to nil, any capitalization is allowed.

Examples:

EnforcedStyle: snake_case (default)

# The `snake_case` style will enforce that the frozen string literal
# comment is written in snake case. (Words separated by underscores)
# bad
# frozen-string-literal: true

module Bar
  # ...
end

# good
# frozen_string_literal: false

module Bar
  # ...
end

EnforcedStyle: kebab_case

# The `kebab_case` style will enforce that the frozen string literal
# comment is written in kebab case. (Words separated by hyphens)
# bad
# frozen_string_literal: true

module Baz
  # ...
end

# good
# frozen-string-literal: true

module Baz
  # ...
end

DirectiveCapitalization: lowercase (default)

# bad
# FROZEN-STRING-LITERAL: true

# good
# frozen-string-literal: true

DirectiveCapitalization: uppercase

# bad
# frozen-string-literal: true

# good
# FROZEN-STRING-LITERAL: true

DirectiveCapitalization: nil

# any capitalization is accepted

# good
# frozen-string-literal: true

# good
# FROZEN-STRING-LITERAL: true

ValueCapitalization: nil (default)

# any capitalization is accepted

# good
# frozen-string-literal: true

# good
# frozen-string-literal: TRUE

ValueCapitalization: lowercase

# when a value is not given, any capitalization is accepted

# bad
# frozen-string-literal: TRUE

# good
# frozen-string-literal: TRUE

ValueCapitalization: uppercase

# bad
# frozen-string-literal: true

# good
# frozen-string-literal: TRUE

Constant Summary

::RuboCop::Cop::Base - Inherited

EMPTY_OFFENSES, RESTRICT_ON_SEND

::RuboCop::Cop::ConfigurableEnforcedStyle - Included

SYMBOL_TO_STRING_CACHE

Class Attribute Summary

::RuboCop::Cop::AutoCorrector - Extended

::RuboCop::Cop::Base - Inherited

.gem_requirements, .lint?,
.support_autocorrect?

Returns if class supports autocorrect.

.support_multiple_source?

Override if your cop should be called repeatedly for multiple investigations Between calls to on_new_investigation and on_investigation_end, the result of processed_source will remain constant.

.builtin?

Class Method Summary

::RuboCop::Cop::Base - Inherited

.autocorrect_incompatible_with

List of cops that should not try to autocorrect at the same time as this cop.

.badge

Naming.

.callbacks_needed, .cop_name, .department,
.documentation_url

Cops (other than builtin) are encouraged to implement this.

.exclude_from_registry

Call for abstract Cop classes.

.inherited,
.joining_forces

Override and return the Force class(es) you need to join.

.match?

Returns true if the cop name or the cop namespace matches any of the given names.

.new,
.requires_gem

Register a version requirement for the given gem name.

.restrict_on_send

::RuboCop::ExcludeLimit - Extended

exclude_limit

Sets up a configuration option to have an exclude limit tracked.

transform

Instance Attribute Summary

Instance Method Summary

::RuboCop::Cop::ConfigurableEnforcedStyle - Included

::RuboCop::Cop::Base - Inherited

#add_global_offense

Adds an offense that has no particular location.

#add_offense

Adds an offense on the specified range (or node with an expression) Unless that offense is disabled for this range, a corrector will be yielded to provide the cop the opportunity to autocorrect the offense.

#begin_investigation

Called before any investigation.

#callbacks_needed,
#cop_config

Configuration Helpers.

#cop_name, #excluded_file?,
#external_dependency_checksum

This method should be overridden when a cop’s behavior depends on state that lives outside of these locations:

#inspect,
#message

Gets called if no message is specified when calling add_offense or add_global_offense Cops are discouraged to override this; instead pass your message directly.

#name

Alias for Base#cop_name.

#offenses,
#on_investigation_end

Called after all on_…​

#on_new_investigation

Called before all on_…​

#on_other_file

Called instead of all on_…​

#parse

There should be very limited reasons for a Cop to do it’s own parsing.

#parser_engine,
#ready

Called between investigations.

#relevant_file?, #target_rails_version, #target_ruby_version, #annotate, #apply_correction, #attempt_correction,
#callback_argument

Reserved for Cop::Cop.

#complete_investigation

Called to complete an investigation.

#correct, #current_corrector,
#current_offense_locations

Reserved for Commissioner:

#current_offenses, #currently_disabled_lines, #custom_severity, #default_severity, #disable_uncorrectable, #enabled_line?, #file_name_matches_any?, #find_message, #find_severity, #range_for_original, #range_from_node_or_range, #reset_investigation, #use_corrector

::RuboCop::Cop::AutocorrectLogic - Included

::RuboCop::Cop::IgnoredNode - Included

Constructor Details

This class inherits a constructor from RuboCop::Cop::Base

Instance Method Details

#correct_separator (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 241

def correct_separator
  style == :snake_case ? SNAKE_SEPARATOR : KEBAB_SEPARATOR
end

#directive_capitalization (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 279

def directive_capitalization
  cop_config['DirectiveCapitalization']&.to_sym.tap do |style|
    unless valid_capitalization?(style)
      raise "Unknown `DirectiveCapitalization` #{style} selected!"
    end
  end
end

#directive_offends?(directive) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 197

def directive_offends?(directive)
  incorrect_separator?(directive.source) ||
    wrong_capitalization?(directive.source, directive_capitalization)
end

#expected_style (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 233

def expected_style
  [directive_capitalization, style].compact.join(' ').gsub(/_?case\b/, '')
end

#find_issues(comment) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 183

def find_issues(comment)
  issues = { directives: [], values: [] }

  comment.directives.each do |directive|
    issues[:directives] << directive if directive_offends?(directive)
  end

  comment.values.each do |value| # rubocop:disable Style/HashEachMethods
    issues[:values] << value if wrong_capitalization?(value.source, value_capitalization)
  end

  issues
end

#fix_directives(issues) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 207

def fix_directives(issues)
  return if issues.empty?

  msg = format(MSG, style: expected_style)

  issues.each do |directive|
    add_offense(directive, message: msg) do |corrector|
      replacement = replace_separator(replace_capitalization(directive.source,
                                                             directive_capitalization))
      corrector.replace(directive, replacement)
    end
  end
end

#fix_values(issues) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 221

def fix_values(issues)
  return if issues.empty?

  msg = format(MSG_VALUE, case: value_capitalization)

  issues.each do |value|
    add_offense(value, message: msg) do |corrector|
      corrector.replace(value, replace_capitalization(value.source, value_capitalization))
    end
  end
end

#incorrect_separator?(text) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 245

def incorrect_separator?(text)
  text[wrong_separator]
end

#leading_comment_lines (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 173

def leading_comment_lines
  first_non_comment_token = processed_source.tokens.find { |token| !token.comment? }

  if first_non_comment_token
    0...first_non_comment_token.line
  else
    (0..)
  end
end

#line_range(line) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 275

def line_range(line)
  processed_source.buffer.line_range(line)
end

#magic_comments (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 167

def magic_comments
  processed_source.each_comment_in_lines(leading_comment_lines)
                  .select { |comment| MagicComment.parse(comment.text).valid? }
                  .map { |comment| CommentRange.new(comment) }
end

#on_new_investigation

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 156

def on_new_investigation
  return unless processed_source.ast

  magic_comments.each do |comment|
    issues = find_issues(comment)
    register_offenses(issues) if issues.any?
  end
end

#register_offenses(issues) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 202

def register_offenses(issues)
  fix_directives(issues[:directives])
  fix_values(issues[:values])
end

#replace_capitalization(text, style) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 264

def replace_capitalization(text, style)
  return text unless style

  case style
  when :lowercase
    text.downcase
  when :uppercase
    text.upcase
  end
end

#replace_separator(text) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 260

def replace_separator(text)
  text.tr(wrong_separator, correct_separator)
end

#supported_capitalizations (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 301

def supported_capitalizations
  cop_config['SupportedCapitalizations'].map(&:to_sym)
end

#valid_capitalization?(style) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 295

def valid_capitalization?(style)
  return true unless style

  supported_capitalizations.include?(style)
end

#value_capitalization (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 287

def value_capitalization
  cop_config['ValueCapitalization']&.to_sym.tap do |style|
    unless valid_capitalization?(style)
      raise "Unknown `ValueCapitalization` #{style} selected!"
    end
  end
end

#wrong_capitalization?(text, expected_case) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 249

def wrong_capitalization?(text, expected_case)
  return false unless expected_case

  case expected_case
  when :lowercase
    text != text.downcase
  when :uppercase
    text != text.upcase
  end
end

#wrong_separator (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/magic_comment_format.rb', line 237

def wrong_separator
  style == :snake_case ? KEBAB_SEPARATOR : SNAKE_SEPARATOR
end