lib/rubocop/cop/surrounding_space.rb in rubocop-0.1.0 vs lib/rubocop/cop/surrounding_space.rb in rubocop-0.2.0
- old
+ new
@@ -1,44 +1,93 @@
+# encoding: utf-8
+
require_relative 'grammar'
module Rubocop
module Cop
class SurroundingSpace < Cop
- ERROR_MESSAGE = 'Surrounding space missing for operator'
+ ERROR_MESSAGE = 'Surrounding space missing for '
def inspect(file, source, tokens, sexp)
- Grammar.new(tokens).correlate(sexp).sort.each { |ix, grammar_path|
- pos, name, text = tokens[ix]
- if name == :on_op
+ Grammar.new(tokens).correlate(sexp).sort.each do |ix, grammar_path|
+ t = tokens[ix]
+ case t.type
+ when :on_op
unless surrounded_by_whitespace?(tokens[ix - 1, 3])
unless ok_without_spaces?(grammar_path)
- index = pos[0] - 1
- add_offence(:convention, index, source[index],
- ERROR_MESSAGE + " '#{text}'.")
+ add_offence(:convention, t.pos.lineno,
+ ERROR_MESSAGE + "operator '#{t.text}'.")
end
end
+ when :on_lbrace
+ unless surrounded_by_whitespace?(tokens[ix - 1, 3])
+ add_offence(:convention, t.pos.lineno, ERROR_MESSAGE + "'{'.")
+ end
+ when :on_rbrace
+ unless whitespace?(tokens[ix - 1])
+ add_offence(:convention, t.pos.lineno,
+ "Space missing to the left of '}'.")
+ end
end
- }
+ end
+ tokens.each_index do |ix|
+ t = tokens[ix]
+ prev, nxt = tokens.values_at(ix - 1, ix + 1)
+ offence_detected = case t.type
+ when :on_lbracket, :on_lparen
+ nxt.type == :on_sp
+ when :on_rbracket, :on_rparen
+ if prev.type == :on_sp
+ prev_ns = previous_non_space(tokens, ix)
+ prev_ns && tokens_on_same_row?(prev_ns,
+ tokens[ix]) &&
+ # Avoid double repoting of [ ] and ( )
+ prev_ns.type != :on_lbracket &&
+ prev_ns.type != :on_lparen
+ end
+ when :on_op
+ t.text == '**' &&
+ (whitespace?(prev) || whitespace?(nxt))
+ end
+ if offence_detected
+ kind = case t.type
+ when :on_lparen, :on_rparen
+ 'inside parentheses'
+ when :on_lbracket, :on_rbracket
+ 'inside square brackets'
+ when :on_op
+ "around operator #{t.text}"
+ end
+ add_offence(:convention, t.pos.lineno, "Space #{kind} detected.")
+ end
+ end
end
+ private
+
+ def tokens_on_same_row?(t1, t2)
+ t1.pos.lineno == t2.pos.lineno
+ end
+
+ def previous_non_space(tokens, ix)
+ (ix - 1).downto(0) do |i|
+ t = tokens[i]
+ return t unless whitespace?(t)
+ end
+ nil
+ end
+
def ok_without_spaces?(grammar_path)
- grandparent, parent, child = grammar_path.values_at(-3, -2, -1)
+ parent, child = grammar_path.values_at(-2, -1)
return true if [:unary, :symbol, :defs, :def, :call].include?(parent)
- return true if [:rest_param, :blockarg, :block_var, :args_add_star,
- :args_add_block, :const_path_ref, :dot2,
- :dot3].include?(child)
- return true if grandparent == :unary && parent == :vcall
+ return true if [:**, :block_var].include?(child)
return true if parent == :command_call && child == :'::'
false
end
def surrounded_by_whitespace?(nearby_tokens)
left, _, right = nearby_tokens
whitespace?(left) && whitespace?(right)
- end
-
- def whitespace?(token)
- [:on_sp, :on_ignored_nl, :on_nl].include?(token[1])
end
end
end
end