lib/tailor/rulers/spaces_before_rbrace_ruler.rb
require_relative '../ruler'
class Tailor
module Rulers
# Checks for spaces before a +}+ as given by +@config+. It skips checking
# when:
# * it's the first char in the line.
# * it's the first char in the line, preceded by spaces.
# * it's directly preceded by a +{+.
class SpacesBeforeRbraceRuler < Tailor::Ruler
def initialize(config, options)
super(config, options)
add_lexer_observers :embexpr_beg, :lbrace, :rbrace
@lbrace_nesting = []
@embexpr_nesting = []
end
# @param [LexedLine] lexed_line
# @param [Fixnum] column
# @return [Fixnum] the number of spaces before the rbrace.
def count_spaces(lexed_line, column)
current_index = lexed_line.event_index(column)
log "Current event index: #{current_index}"
previous_event = lexed_line.at(current_index - 1)
log "Previous event: #{previous_event}"
if column.zero? || previous_event.nil?
log 'rbrace is at the beginning of the line.'
@do_measurement = false
return 0
end
if previous_event[1] == :on_lbrace
log "rbrace comes after a '{'"
@do_measurement = false
return 0
end
return 0 if previous_event[1] != :on_sp
if current_index - 2 < 0
log 'rbrace is at the beginning of an indented line. Moving on.'
@do_measurement = false
return previous_event.last.size
end
previous_event.last.size
end
def embexpr_beg_update(_, _, _)
if RUBY_VERSION < '2.0.0'
@lbrace_nesting << :embexpr_beg
end
end
def lbrace_update(_, _, _)
@lbrace_nesting << :lbrace
end
# Checks to see if the number of spaces before an rbrace equals the value
# at +@config+.
#
# @param [Fixnum] actual_spaces The number of spaces after the rbrace.
# @param [Fixnum] lineno Line the problem was found on.
# @param [Fixnum] column Column the problem was found on.
def measure(actual_spaces, lineno, column)
if actual_spaces != @config
msg = "Line has #{actual_spaces} space(s) before a }, "
msg << "but should have #{@config}."
@problems << Problem.new(problem_type, lineno, column, msg,
@options[:level])
end
end
# For Ruby versions < 2.0.0-p0, this has to keep track of +{+'s and only
# follow through with the check if the +{+ was an lbrace because Ripper
# doesn't scan the +}+ of an embedded expression (embexpr_end) as such.
#
# @param [Tailor::LexedLine] lexed_line
# @param [Fixnum] lineno
# @param [Fixnum] column
def rbrace_update(lexed_line, lineno, column)
if RUBY_VERSION < '2.0.0' && @lbrace_nesting.last == :embexpr_beg
@lbrace_nesting.pop
return
end
@lbrace_nesting.pop
count = count_spaces(lexed_line, column)
log "Found #{count} space(s) before rbrace."
if !@do_measurement
log 'Skipping measurement.'
else
measure(count, lineno, column)
end
@do_measurement = true
end
end
end
end