class RuboCop::Cop::Style::Semicolon
foo = 1; bar = 2
# good
@example AllowAsExpressionSeparator: true
foo = 1; bar = 2
# bad
@example AllowAsExpressionSeparator: false (default)
baz = 3
bar = 2
foo = 1
# good
baz = 3;
foo = 1; bar = 2;
# bad
@example
It allows ‘;` to separate several expressions on the same line.
This cop has `AllowAsExpressionSeparator` configuration option.
It also checks for lines terminated with a semicolon.
This cop checks for multiple expressions placed on the same line.
def self.autocorrect_incompatible_with
def self.autocorrect_incompatible_with [Style::SingleLineMethods] end
def check_for_line_terminator_or_opener
def check_for_line_terminator_or_opener # Make the obvious check first return unless processed_source.raw_source.include?(';') each_semicolon { |line, column| register_semicolon(line, column, false) } end
def each_semicolon
def each_semicolon tokens_for_lines.each do |line, tokens| yield line, tokens.last.column if tokens.last.semicolon? yield line, tokens.first.column if tokens.first.semicolon? end end
def expressions_per_line(exprs)
def expressions_per_line(exprs) # create a map matching lines to the number of expressions on them exprs_lines = exprs.map(&:first_line) exprs_lines.group_by(&:itself) end
def find_semicolon_positions(line)
def find_semicolon_positions(line) # Scan for all the semicolons on the line semicolons = processed_source[line - 1].enum_for(:scan, ';') semicolons.each do yield Regexp.last_match.begin(0) end end
def on_begin(node)
def on_begin(node) return if cop_config['AllowAsExpressionSeparator'] exprs = node.children return if exprs.size < 2 expressions_per_line(exprs).each do |line, expr_on_line| # Every line with more than one expression on it is a # potential offense next unless expr_on_line.size > 1 find_semicolon_positions(line) { |pos| register_semicolon(line, pos, true) } end end
def on_new_investigation
def on_new_investigation return if processed_source.blank? check_for_line_terminator_or_opener end
def register_semicolon(line, column, after_expression)
def register_semicolon(line, column, after_expression) range = source_range(processed_source.buffer, line, column) add_offense(range) do |corrector| if after_expression corrector.replace(range, "\n") else corrector.remove(range) end end end
def tokens_for_lines
def tokens_for_lines processed_source.tokens.group_by(&:line) end