Class: RuboCop::Cop::Style::HashSyntax

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Includes:
ConfigurableEnforcedStyle, HashShorthandSyntax, RangeHelp
Defined in:
lib/rubocop/cop/style/hash_syntax.rb

Overview

This cop checks hash literal syntax.

It can enforce either the use of the class hash rocket syntax or the use of the newer Ruby 1.9 syntax (when applicable).

A separate offense is registered for each problematic pair.

The supported styles are:

  • ruby19 - forces use of the 1.9 syntax (e.g. {a: 1}) when hashes have all symbols for keys
  • hash_rockets - forces use of hash rockets for all hashes
  • no_mixed_keys - simply checks for hashes with mixed syntaxes
  • ruby19_no_mixed_keys - forces use of ruby 1.9 syntax and forbids mixed syntax hashes

This cop has EnforcedShorthandSyntax option. It can enforce either the use of the explicit hash value syntax or the use of Ruby 3.1's hash value shorthand syntax.

The supported styles are:

  • always - forces use of the 3.1 syntax (e.g. foo:)
  • never - forces use of explicit hash literal value
  • either - accepts both shorthand and explicit use of hash literal value

Examples:

EnforcedStyle: ruby19 (default)

# bad
{:a => 2}
{b: 1, :c => 2}

# good
{a: 2, b: 1}
{:c => 2, 'd' => 2} # acceptable since 'd' isn't a symbol
{d: 1, 'e' => 2} # technically not forbidden

EnforcedStyle: hash_rockets

# bad
{a: 1, b: 2}
{c: 1, 'd' => 5}

# good
{:a => 1, :b => 2}

EnforcedStyle: no_mixed_keys

# bad
{:a => 1, b: 2}
{c: 1, 'd' => 2}

# good
{:a => 1, :b => 2}
{c: 1, d: 2}

EnforcedStyle: ruby19_no_mixed_keys

# bad
{:a => 1, :b => 2}
{c: 2, 'd' => 3} # should just use hash rockets

# good
{a: 1, b: 2}
{:c => 3, 'd' => 4}

EnforcedShorthandSyntax: always (default)


# bad
{foo: foo, bar: bar}

# good
{foo:, bar:}

EnforcedShorthandSyntax: never


# bad
{foo:, bar:}

# good
{foo: foo, bar: bar}

EnforcedShorthandSyntax: either


# good
{foo: foo, bar: bar}

# good
{foo:, bar:}

Constant Summary collapse

MSG_19 =
'Use the new Ruby 1.9 hash syntax.'
MSG_NO_MIXED_KEYS =
"Don't mix styles in the same hash."
MSG_HASH_ROCKETS =
'Use hash rockets syntax.'

Constants included from HashShorthandSyntax

HashShorthandSyntax::EXPLICIT_HASH_VALUE_MSG, HashShorthandSyntax::OMIT_HASH_VALUE_MSG

Constants inherited from Base

Base::RESTRICT_ON_SEND

Instance Attribute Summary

Attributes inherited from Base

#config, #processed_source

Instance Method Summary collapse

Methods included from AutoCorrector

support_autocorrect?

Methods included from HashShorthandSyntax

#on_pair

Methods included from ConfigurableEnforcedStyle

#alternative_styles, #ambiguous_style_detected, #correct_style_detected, #detected_style, #detected_style=, #no_acceptable_style!, #no_acceptable_style?, #opposite_style_detected, #style, #style_configured?, #style_detected, #style_parameter_name, #supported_styles, #unexpected_style_detected

Methods inherited from Base

#add_global_offense, #add_offense, autocorrect_incompatible_with, badge, #callbacks_needed, callbacks_needed, #config_to_allow_offenses, #config_to_allow_offenses=, #cop_config, #cop_name, cop_name, department, documentation_url, exclude_from_registry, #excluded_file?, #external_dependency_checksum, inherited, #initialize, joining_forces, lint?, match?, #message, #offenses, #on_investigation_end, #on_new_investigation, #on_other_file, #parse, #ready, #relevant_file?, support_autocorrect?, support_multiple_source?, #target_rails_version, #target_ruby_version

Methods included from ExcludeLimit

#exclude_limit

Methods included from AutocorrectLogic

#autocorrect?, #autocorrect_enabled?, #autocorrect_requested?, #autocorrect_with_disable_uncorrectable?, #correctable?, #disable_uncorrectable?, #safe_autocorrect?

Methods included from IgnoredNode

#ignore_node, #ignored_node?, #part_of_ignored_node?

Methods included from Util

silence_warnings

Constructor Details

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

Instance Method Details

#alternative_styleObject


144
145
146
147
148
149
150
151
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 144

def alternative_style
  case style
  when :hash_rockets
    :ruby19
  when :ruby19, :ruby19_no_mixed_keys
    :hash_rockets
  end
end

#hash_rockets_check(pairs) ⇒ Object


122
123
124
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 122

def hash_rockets_check(pairs)
  check(pairs, ':', MSG_HASH_ROCKETS)
end

#no_mixed_keys_check(pairs) ⇒ Object


136
137
138
139
140
141
142
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 136

def no_mixed_keys_check(pairs)
  if sym_indices?(pairs)
    check(pairs, pairs.first.inverse_delimiter, MSG_NO_MIXED_KEYS)
  else
    check(pairs, ':', MSG_NO_MIXED_KEYS)
  end
end

#on_hash(node) ⇒ Object


102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 102

def on_hash(node)
  pairs = node.pairs

  return if pairs.empty?

  if style == :hash_rockets || force_hash_rockets?(pairs)
    hash_rockets_check(pairs)
  elsif style == :ruby19_no_mixed_keys
    ruby19_no_mixed_keys_check(pairs)
  elsif style == :no_mixed_keys
    no_mixed_keys_check(pairs)
  else
    ruby19_check(pairs)
  end
end

#ruby19_check(pairs) ⇒ Object


118
119
120
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 118

def ruby19_check(pairs)
  check(pairs, '=>', MSG_19) if sym_indices?(pairs)
end

#ruby19_no_mixed_keys_check(pairs) ⇒ Object


126
127
128
129
130
131
132
133
134
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 126

def ruby19_no_mixed_keys_check(pairs)
  if force_hash_rockets?(pairs)
    check(pairs, ':', MSG_HASH_ROCKETS)
  elsif sym_indices?(pairs)
    check(pairs, '=>', MSG_19)
  else
    check(pairs, ':', MSG_NO_MIXED_KEYS)
  end
end