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

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

  • consistent - forces use of the 3.1 syntax only if all values can be omitted in the hash

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: foo, bar:}

# good
{foo:, bar:}

EnforcedShorthandSyntax: consistent


# bad - `foo` and `bar` values can be omitted
{foo: foo, bar: bar}

# bad - `bar` value can be omitted
{foo:, bar: bar}

# bad - mixed syntaxes
{foo:, bar: baz}

# good
{foo:, bar:}

# good - can't omit `baz`
{foo: foo, bar: baz}

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::DO_NOT_MIX_EXPLICIT_VALUE_MSG, HashShorthandSyntax::DO_NOT_MIX_MSG_PREFIX, HashShorthandSyntax::DO_NOT_MIX_OMIT_VALUE_MSG, 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_hash_for_mixed_shorthand, #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

#active_support_extensions_enabled?, #add_global_offense, #add_offense, autocorrect_incompatible_with, badge, #begin_investigation, 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, #inspect, 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



167
168
169
170
171
172
173
174
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 167

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

#hash_rockets_check(pairs) ⇒ Object



145
146
147
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 145

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

#no_mixed_keys_check(pairs) ⇒ Object



159
160
161
162
163
164
165
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 159

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



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 123

def on_hash(node)
  pairs = node.pairs

  return if pairs.empty?

  on_hash_for_mixed_shorthand(node)

  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



141
142
143
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 141

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

#ruby19_no_mixed_keys_check(pairs) ⇒ Object



149
150
151
152
153
154
155
156
157
# File 'lib/rubocop/cop/style/hash_syntax.rb', line 149

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