123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::Cop::Layout::SpaceInsideBlockBraces

Relationships & Source Files
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/layout/space_inside_block_braces.rb

Overview

Checks that block braces have or don’t have surrounding space inside them on configuration. For blocks taking parameters, it checks that the left brace has or doesn’t have trailing space depending on configuration.

Examples:

EnforcedStyle: space (default)

# The `space` style enforces that block braces have
# surrounding space.

# bad
some_array.each {puts e}

# good
some_array.each { puts e }

EnforcedStyle: no_space

# The `no_space` style enforces that block braces don't
# have surrounding space.

# bad
some_array.each { puts e }

# good
some_array.each {puts e}

EnforcedStyleForEmptyBraces: no_space (default)

# The `no_space` EnforcedStyleForEmptyBraces style enforces that
# block braces don't have a space in between when empty.

# bad
some_array.each {   }
some_array.each {  }
some_array.each { }

# good
some_array.each {}

EnforcedStyleForEmptyBraces: space

# The `space` EnforcedStyleForEmptyBraces style enforces that
# block braces have at least a space in between when empty.

# bad
some_array.each {}

# good
some_array.each { }
some_array.each {  }
some_array.each {   }

SpaceBeforeBlockParameters: true (default)

# The SpaceBeforeBlockParameters style set to `true` enforces that
# there is a space between `{` and `|`. Overrides `EnforcedStyle`
# if there is a conflict.

# bad
[1, 2, 3].each {|n| n * 2 }

# good
[1, 2, 3].each { |n| n * 2 }

SpaceBeforeBlockParameters: false

# The SpaceBeforeBlockParameters style set to `false` enforces that
# there is no space between `{` and `|`. Overrides `EnforcedStyle`
# if there is a conflict.

# bad
[1, 2, 3].each { |n| n * 2 }

# good
[1, 2, 3].each {|n| n * 2 }

Constant Summary

::RuboCop::Cop::Base - Inherited

EMPTY_OFFENSES, RESTRICT_ON_SEND

::RuboCop::Cop::ConfigurableEnforcedStyle - Included

SYMBOL_TO_STRING_CACHE

::RuboCop::Cop::RangeHelp - Included

BYTE_ORDER_MARK, NOT_GIVEN

::RuboCop::Cop::SurroundingSpace - Included

NO_SPACE_COMMAND, SINGLE_SPACE_REGEXP, SPACE_COMMAND

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::SurroundingSpace - Included

::RuboCop::Cop::RangeHelp - Included

#add_range, #column_offset_between,
#contents_range

A range containing only the contents of a literal with delimiters (e.g.

#directions,
#effective_column

Returns the column attribute of the range, except if the range is on the first line and there’s a byte order mark at the beginning of that line, in which case 1 is subtracted from the column value.

#final_pos, #move_pos, #move_pos_str, #range_between, #range_by_whole_lines, #range_with_comments, #range_with_comments_and_lines, #range_with_surrounding_comma, #range_with_surrounding_space, #source_range

::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

#adjacent_braces(left_brace, right_brace) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 122

def adjacent_braces(left_brace, right_brace)
  return if style_for_empty_braces != :space

  offense(left_brace.begin_pos, right_brace.end_pos,
          'Space missing inside empty braces.',
          'EnforcedStyleForEmptyBraces')
end

#aligned_braces?(inner, right_brace, column) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 161

def aligned_braces?(inner, right_brace, column)
  column == right_brace.column || column == inner_last_space_count(inner)
end

#braces_with_contents_inside(node, inner) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 130

def braces_with_contents_inside(node, inner)
  args_delimiter = node.arguments.loc.begin if node.block_type? # Can be ( | or nil.

  check_left_brace(inner, node.loc.begin, args_delimiter)
  check_right_brace(node, inner, node.loc.begin, node.loc.end, node.single_line?)
end

#check_inside(node, left_brace, right_brace) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 105

def check_inside(node, left_brace, right_brace)
  if left_brace.end_pos == right_brace.begin_pos
    adjacent_braces(left_brace, right_brace)
  else
    range = range_between(left_brace.end_pos, right_brace.begin_pos)
    inner = range.source

    if /\S/.match?(inner)
      braces_with_contents_inside(node, inner)
    elsif style_for_empty_braces == :no_space
      offense(range.begin_pos, range.end_pos,
              'Space inside empty braces detected.',
              'EnforcedStyleForEmptyBraces')
    end
  end
end

#check_left_brace(inner, left_brace, args_delimiter) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 137

def check_left_brace(inner, left_brace, args_delimiter)
  if /\A\S/.match?(inner)
    no_space_inside_left_brace(left_brace, args_delimiter)
  else
    space_inside_left_brace(left_brace, args_delimiter)
  end
end

#check_right_brace(node, inner, left_brace, right_brace, single_line) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 145

def check_right_brace(node, inner, left_brace, right_brace, single_line)
  if single_line && /\S$/.match?(inner)
    no_space(right_brace.begin_pos, right_brace.end_pos, 'Space missing inside }.')
  else
    column = node.source_range.column
    return if multiline_block?(left_brace, right_brace) &&
              aligned_braces?(inner, right_brace, column)

    space_inside_right_brace(inner, right_brace, column)
  end
end

#inner_last_space_count(inner) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 165

def inner_last_space_count(inner)
  inner.split("\n").last.count(' ')
end

#multiline_block?(left_brace, right_brace) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 157

def multiline_block?(left_brace, right_brace)
  left_brace.first_line != right_brace.first_line
end

#no_space(begin_pos, end_pos, msg) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 222

def no_space(begin_pos, end_pos, msg)
  if style == :space
    offense(begin_pos, end_pos, msg)
  else
    correct_style_detected
  end
end

#no_space_inside_left_brace(left_brace, args_delimiter) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 169

def no_space_inside_left_brace(left_brace, args_delimiter)
  if pipe?(args_delimiter)
    if left_brace.end_pos == args_delimiter.begin_pos &&
       cop_config['SpaceBeforeBlockParameters']
      offense(left_brace.begin_pos, args_delimiter.end_pos,
              'Space between { and | missing.')
    else
      correct_style_detected
    end
  else
    # We indicate the position after the left brace. Otherwise it's
    # difficult to distinguish between space missing to the left and to
    # the right of the brace in autocorrect.
    no_space(left_brace.end_pos, left_brace.end_pos + 1, 'Space missing inside {.')
  end
end

#offense(begin_pos, end_pos, msg, style_param = 'EnforcedStyle') (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 238

def offense(begin_pos, end_pos, msg, style_param = 'EnforcedStyle')
  return if begin_pos > end_pos

  range = range_between(begin_pos, end_pos)
  add_offense(range, message: msg) do |corrector|
    case range.source
    when /\s/ then corrector.remove(range)
    when '{}' then corrector.replace(range, '{ }')
    when '{|' then corrector.replace(range, '{ |')
    else           corrector.insert_before(range, ' ')
    end
    opposite_style_detected if style_param == 'EnforcedStyle'
  end
end

#on_block(node) Also known as: #on_numblock

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 85

def on_block(node)
  return if node.keywords?

  # Do not register an offense for multi-line empty braces. That means
  # preventing autocorrection to single-line empty braces. It will
  # conflict with autocorrection by `Layout/SpaceInsideBlockBraces` cop
  # if autocorrected to a single-line empty braces.
  # See: https://github.com/rubocop/rubocop/issues/7363
  return if node.body.nil? && node.multiline?

  left_brace = node.loc.begin
  right_brace = node.loc.end

  check_inside(node, left_brace, right_brace)
end

#on_numblock(node)

Alias for #on_block.

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 101

alias on_numblock on_block

#pipe?(args_delimiter) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 201

def pipe?(args_delimiter)
  args_delimiter&.is?('|')
end

#space(begin_pos, end_pos, msg) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 230

def space(begin_pos, end_pos, msg)
  if style == :no_space
    offense(begin_pos, end_pos, msg)
  else
    correct_style_detected
  end
end

#space_inside_left_brace(left_brace, args_delimiter) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 186

def space_inside_left_brace(left_brace, args_delimiter)
  if pipe?(args_delimiter)
    if cop_config['SpaceBeforeBlockParameters']
      correct_style_detected
    else
      offense(left_brace.end_pos, args_delimiter.begin_pos,
              'Space between { and | detected.')
    end
  else
    brace_with_space = range_with_surrounding_space(left_brace, side: :right)
    space(brace_with_space.begin_pos + 1, brace_with_space.end_pos,
          'Space inside { detected.')
  end
end

#space_inside_right_brace(inner, right_brace, column) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 205

def space_inside_right_brace(inner, right_brace, column)
  brace_with_space = range_with_surrounding_space(right_brace, side: :left)
  begin_pos = brace_with_space.begin_pos
  end_pos = brace_with_space.end_pos - 1

  if brace_with_space.source.match?(/\R/)
    begin_pos = end_pos - (right_brace.column - column)
  end

  if inner.end_with?(']')
    end_pos -= 1
    begin_pos = end_pos - (inner_last_space_count(inner) - column)
  end

  space(begin_pos, end_pos, 'Space inside } detected.')
end

#style_for_empty_braces (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/space_inside_block_braces.rb', line 253

def style_for_empty_braces
  case cop_config['EnforcedStyleForEmptyBraces']
  when 'space'    then :space
  when 'no_space' then :no_space
  else raise 'Unknown EnforcedStyleForEmptyBraces selected!'
  end
end