rubocop 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +7 -1
- data/CHANGELOG.md +19 -0
- data/README.md +4 -8
- data/bin/rubocop +2 -2
- data/config/default.yml +8 -0
- data/config/enabled.yml +21 -24
- data/lib/rubocop.rb +9 -7
- data/lib/rubocop/cli.rb +73 -52
- data/lib/rubocop/config.rb +8 -5
- data/lib/rubocop/cop/access_control.rb +41 -0
- data/lib/rubocop/cop/alias.rb +7 -5
- data/lib/rubocop/cop/align_parameters.rb +20 -96
- data/lib/rubocop/cop/and_or.rb +26 -0
- data/lib/rubocop/cop/ascii_comments.rb +3 -8
- data/lib/rubocop/cop/ascii_identifiers.rb +6 -5
- data/lib/rubocop/cop/avoid_class_vars.rb +5 -10
- data/lib/rubocop/cop/avoid_for.rb +7 -5
- data/lib/rubocop/cop/avoid_global_vars.rb +19 -7
- data/lib/rubocop/cop/avoid_perl_backrefs.rb +7 -10
- data/lib/rubocop/cop/avoid_perlisms.rb +11 -10
- data/lib/rubocop/cop/block_comments.rb +4 -6
- data/lib/rubocop/cop/blocks.rb +11 -47
- data/lib/rubocop/cop/case_indentation.rb +9 -31
- data/lib/rubocop/cop/class_and_module_camel_case.rb +20 -11
- data/lib/rubocop/cop/class_methods.rb +5 -10
- data/lib/rubocop/cop/collection_methods.rb +16 -16
- data/lib/rubocop/cop/colon_method_call.rb +8 -32
- data/lib/rubocop/cop/constant_name.rb +24 -0
- data/lib/rubocop/cop/cop.rb +20 -78
- data/lib/rubocop/cop/def_parentheses.rb +43 -35
- data/lib/rubocop/cop/empty_line_between_defs.rb +11 -15
- data/lib/rubocop/cop/empty_lines.rb +20 -9
- data/lib/rubocop/cop/empty_literal.rb +47 -0
- data/lib/rubocop/cop/encoding.rb +3 -3
- data/lib/rubocop/cop/end_of_line.rb +3 -3
- data/lib/rubocop/cop/ensure_return.rb +6 -23
- data/lib/rubocop/cop/eval.rb +7 -10
- data/lib/rubocop/cop/favor_join.rb +9 -24
- data/lib/rubocop/cop/favor_modifier.rb +38 -48
- data/lib/rubocop/cop/favor_percent_r.rb +7 -7
- data/lib/rubocop/cop/favor_sprintf.rb +8 -24
- data/lib/rubocop/cop/favor_unless_over_negated_if.rb +19 -17
- data/lib/rubocop/cop/handle_exceptions.rb +7 -11
- data/lib/rubocop/cop/hash_syntax.rb +29 -14
- data/lib/rubocop/cop/if_then_else.rb +32 -29
- data/lib/rubocop/cop/leading_comment_space.rb +5 -8
- data/lib/rubocop/cop/line_continuation.rb +4 -7
- data/lib/rubocop/cop/line_length.rb +3 -3
- data/lib/rubocop/cop/loop.rb +33 -0
- data/lib/rubocop/cop/method_and_variable_snake_case.rb +42 -19
- data/lib/rubocop/cop/method_length.rb +34 -37
- data/lib/rubocop/cop/new_lambda_literal.rb +8 -6
- data/lib/rubocop/cop/not.rb +10 -4
- data/lib/rubocop/cop/numeric_literals.rb +9 -7
- data/lib/rubocop/cop/offence.rb +1 -1
- data/lib/rubocop/cop/op_method.rb +12 -22
- data/lib/rubocop/cop/parameter_lists.rb +12 -6
- data/lib/rubocop/cop/parentheses_around_condition.rb +11 -11
- data/lib/rubocop/cop/percent_r.rb +7 -7
- data/lib/rubocop/cop/reduce_arguments.rb +13 -51
- data/lib/rubocop/cop/rescue_exception.rb +13 -29
- data/lib/rubocop/cop/rescue_modifier.rb +5 -8
- data/lib/rubocop/cop/semicolon.rb +15 -74
- data/lib/rubocop/cop/single_line_methods.rb +28 -44
- data/lib/rubocop/cop/space_after_comma_etc.rb +29 -9
- data/lib/rubocop/cop/space_after_control_keyword.rb +16 -15
- data/lib/rubocop/cop/string_literals.rb +9 -35
- data/lib/rubocop/cop/surrounding_space.rb +213 -112
- data/lib/rubocop/cop/symbol_array.rb +9 -7
- data/lib/rubocop/cop/symbol_name.rb +23 -0
- data/lib/rubocop/cop/syntax.rb +14 -7
- data/lib/rubocop/cop/tab.rb +3 -3
- data/lib/rubocop/cop/ternary_operator.rb +26 -24
- data/lib/rubocop/cop/trailing_whitespace.rb +3 -5
- data/lib/rubocop/cop/trivial_accessors.rb +18 -95
- data/lib/rubocop/cop/unless_else.rb +11 -7
- data/lib/rubocop/cop/util.rb +26 -0
- data/lib/rubocop/cop/variable_interpolation.rb +18 -10
- data/lib/rubocop/cop/when_then.rb +6 -17
- data/lib/rubocop/cop/word_array.rb +18 -19
- data/lib/rubocop/version.rb +1 -1
- data/rubocop.gemspec +1 -0
- data/spec/project_spec.rb +1 -1
- data/spec/rubocop/cli_spec.rb +16 -9
- data/spec/rubocop/config_spec.rb +13 -3
- data/spec/rubocop/cops/access_control_spec.rb +129 -0
- data/spec/rubocop/cops/alias_spec.rb +2 -6
- data/spec/rubocop/cops/align_parameters_spec.rb +58 -71
- data/spec/rubocop/cops/and_or_spec.rb +37 -0
- data/spec/rubocop/cops/ascii_comments_spec.rb +3 -4
- data/spec/rubocop/cops/ascii_identifiers_spec.rb +3 -4
- data/spec/rubocop/cops/avoid_class_vars_spec.rb +7 -2
- data/spec/rubocop/cops/avoid_for_spec.rb +1 -4
- data/spec/rubocop/cops/{avoid_global_vars.rb → avoid_global_vars_spec.rb} +4 -4
- data/spec/rubocop/cops/avoid_perl_backrefs_spec.rb +1 -1
- data/spec/rubocop/cops/avoid_perlisms_spec.rb +5 -5
- data/spec/rubocop/cops/block_comments_spec.rb +0 -4
- data/spec/rubocop/cops/blocks_spec.rb +33 -0
- data/spec/rubocop/cops/case_indentation_spec.rb +5 -5
- data/spec/rubocop/cops/class_and_module_camel_case_spec.rb +15 -5
- data/spec/rubocop/cops/class_methods_spec.rb +4 -4
- data/spec/rubocop/cops/collection_methods_spec.rb +9 -4
- data/spec/rubocop/cops/colon_method_call_spec.rb +11 -5
- data/spec/rubocop/cops/constant_name_spec.rb +42 -0
- data/spec/rubocop/cops/def_with_parentheses_spec.rb +13 -8
- data/spec/rubocop/cops/def_without_parentheses_spec.rb +11 -5
- data/spec/rubocop/cops/empty_line_between_defs_spec.rb +38 -38
- data/spec/rubocop/cops/empty_lines_spec.rb +15 -3
- data/spec/rubocop/cops/empty_literal_spec.rb +90 -0
- data/spec/rubocop/cops/encoding_spec.rb +9 -9
- data/spec/rubocop/cops/end_of_line_spec.rb +2 -2
- data/spec/rubocop/cops/ensure_return_spec.rb +1 -3
- data/spec/rubocop/cops/eval_spec.rb +8 -5
- data/spec/rubocop/cops/favor_join_spec.rb +1 -5
- data/spec/rubocop/cops/favor_modifier_spec.rb +16 -14
- data/spec/rubocop/cops/{favor_percent_r.rb → favor_percent_r_spec.rb} +6 -6
- data/spec/rubocop/cops/favor_sprintf_spec.rb +3 -9
- data/spec/rubocop/cops/favor_unless_over_negated_if_spec.rb +4 -4
- data/spec/rubocop/cops/favor_until_over_negated_while_spec.rb +3 -3
- data/spec/rubocop/cops/handle_exceptions_spec.rb +1 -3
- data/spec/rubocop/cops/hash_syntax_spec.rb +11 -6
- data/spec/rubocop/cops/if_with_semicolon_spec.rb +7 -1
- data/spec/rubocop/cops/leading_comment_space_spec.rb +0 -7
- data/spec/rubocop/cops/line_continuation_spec.rb +2 -2
- data/spec/rubocop/cops/line_length_spec.rb +2 -2
- data/spec/rubocop/cops/loop_spec.rb +31 -0
- data/spec/rubocop/cops/method_and_variable_snake_case_spec.rb +38 -12
- data/spec/rubocop/cops/method_length_spec.rb +85 -85
- data/spec/rubocop/cops/multiline_if_then_spec.rb +15 -15
- data/spec/rubocop/cops/new_lambda_literal_spec.rb +3 -3
- data/spec/rubocop/cops/not_spec.rb +1 -4
- data/spec/rubocop/cops/numeric_literals_spec.rb +13 -13
- data/spec/rubocop/cops/one_line_conditional_spec.rb +1 -1
- data/spec/rubocop/cops/op_method_spec.rb +2 -9
- data/spec/rubocop/cops/parameter_lists_spec.rb +7 -7
- data/spec/rubocop/cops/parentheses_around_condition_spec.rb +41 -44
- data/spec/rubocop/cops/percent_r_spec.rb +6 -6
- data/spec/rubocop/cops/reduce_arguments_spec.rb +4 -4
- data/spec/rubocop/cops/rescue_exception_spec.rb +48 -8
- data/spec/rubocop/cops/rescue_modifier_spec.rb +2 -5
- data/spec/rubocop/cops/semicolon_spec.rb +2 -30
- data/spec/rubocop/cops/single_line_methods_spec.rb +13 -13
- data/spec/rubocop/cops/space_after_colon_spec.rb +3 -3
- data/spec/rubocop/cops/space_after_comma_spec.rb +14 -2
- data/spec/rubocop/cops/space_after_control_keyword_spec.rb +42 -3
- data/spec/rubocop/cops/space_after_semicolon_spec.rb +2 -2
- data/spec/rubocop/cops/space_around_braces_spec.rb +18 -3
- data/spec/rubocop/cops/space_around_equals_in_default_parameter_spec.rb +4 -4
- data/spec/rubocop/cops/space_around_operators_spec.rb +82 -27
- data/spec/rubocop/cops/space_inside_brackets_spec.rb +13 -7
- data/spec/rubocop/cops/space_inside_hash_literal_braces_spec.rb +14 -9
- data/spec/rubocop/cops/space_inside_parens_spec.rb +7 -3
- data/spec/rubocop/cops/string_literals_spec.rb +17 -5
- data/spec/rubocop/cops/symbol_array_spec.rb +18 -2
- data/spec/rubocop/cops/symbol_name_spec.rb +119 -0
- data/spec/rubocop/cops/syntax_spec.rb +25 -18
- data/spec/rubocop/cops/tab_spec.rb +2 -2
- data/spec/rubocop/cops/ternary_operator_spec.rb +13 -17
- data/spec/rubocop/cops/trailing_whitespace_spec.rb +3 -3
- data/spec/rubocop/cops/trivial_accessors_spec.rb +17 -20
- data/spec/rubocop/cops/unless_else_spec.rb +8 -8
- data/spec/rubocop/cops/variable_interpolation_spec.rb +0 -5
- data/spec/rubocop/cops/when_then_spec.rb +14 -21
- data/spec/rubocop/cops/word_array_spec.rb +12 -4
- data/spec/spec_helper.rb +12 -4
- metadata +40 -31
- data/.document +0 -5
- data/lib/rubocop/cop/ampersands_pipes_vs_and_or.rb +0 -25
- data/lib/rubocop/cop/array_literal.rb +0 -61
- data/lib/rubocop/cop/brace_after_percent.rb +0 -32
- data/lib/rubocop/cop/grammar.rb +0 -138
- data/lib/rubocop/cop/hash_literal.rb +0 -61
- data/lib/rubocop/cop/percent_literals.rb +0 -25
- data/lib/rubocop/cop/symbol_snake_case.rb +0 -47
- data/spec/rubocop/cops/ampersands_pipes_vs_and_or_spec.rb +0 -57
- data/spec/rubocop/cops/array_literal_spec.rb +0 -46
- data/spec/rubocop/cops/brace_after_percent_spec.rb +0 -33
- data/spec/rubocop/cops/grammar_spec.rb +0 -81
- data/spec/rubocop/cops/hash_literal_spec.rb +0 -46
- data/spec/rubocop/cops/multiline_blocks_spec.rb +0 -24
- data/spec/rubocop/cops/percent_literals_spec.rb +0 -47
- data/spec/rubocop/cops/single_line_blocks_spec.rb +0 -22
- data/spec/rubocop/cops/symbol_snake_case_spec.rb +0 -93
@@ -3,57 +3,41 @@
|
|
3
3
|
module Rubocop
|
4
4
|
module Cop
|
5
5
|
class SingleLineMethods < Cop
|
6
|
-
|
6
|
+
MSG = 'Avoid single-line method definitions.'
|
7
7
|
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
end
|
8
|
+
def allow_empty?
|
9
|
+
SingleLineMethods.config['AllowIfMethodIsEmpty']
|
10
|
+
end
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
if [token.type, token.text] == [:on_kw, 'def']
|
26
|
-
lineno_of_def = token.pos.lineno
|
27
|
-
name_token = tokens[ix..-1].find do |t|
|
28
|
-
[:on_ident, :on_const].include?(t.type)
|
29
|
-
end
|
30
|
-
possible_offence =
|
31
|
-
if SingleLineMethods.config['AllowIfMethodIsEmpty']
|
32
|
-
!is_empty[name_token.pos]
|
33
|
-
else
|
34
|
-
true
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
12
|
+
def on_def(node)
|
13
|
+
check(node)
|
14
|
+
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_defs(node)
|
19
|
+
check(node)
|
20
|
+
|
21
|
+
super
|
38
22
|
end
|
39
23
|
|
40
24
|
private
|
41
25
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
26
|
+
def check(node)
|
27
|
+
start_line = node.loc.keyword.line
|
28
|
+
end_line = node.loc.end.line
|
29
|
+
|
30
|
+
if node.type == :def
|
31
|
+
empty_body = node.children[2].type == :nil
|
32
|
+
else
|
33
|
+
empty_body = node.children[3].type == :nil
|
34
|
+
end
|
35
|
+
|
36
|
+
if start_line == end_line && !(allow_empty? && empty_body)
|
37
|
+
add_offence(:convention,
|
38
|
+
start_line,
|
39
|
+
MSG)
|
55
40
|
end
|
56
|
-
is_empty
|
57
41
|
end
|
58
42
|
end
|
59
43
|
end
|
@@ -1,40 +1,60 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
# rubocop:disable SymbolName
|
4
|
+
|
3
5
|
module Rubocop
|
4
6
|
module Cop
|
5
7
|
module SpaceAfterCommaEtc
|
6
|
-
|
8
|
+
MSG = 'Space missing after %s.'
|
7
9
|
|
8
|
-
def inspect(
|
10
|
+
def inspect(source, tokens, ast, comments)
|
9
11
|
tokens.each_cons(2) do |t1, t2|
|
10
|
-
if kind(t1) &&
|
11
|
-
|
12
|
-
|
12
|
+
if kind(t1) && t1.pos.line == t2.pos.line &&
|
13
|
+
t2.pos.column == t1.pos.column + offset(t1)
|
14
|
+
add_offence(:convention, t1.pos.line, sprintf(MSG, kind(t1)))
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
18
|
+
|
19
|
+
# The normal offset, i.e., the distance from the punctuation
|
20
|
+
# token where a space should be, is 1.
|
21
|
+
def offset(token)
|
22
|
+
1
|
23
|
+
end
|
16
24
|
end
|
17
25
|
|
18
26
|
class SpaceAfterComma < Cop
|
19
27
|
include SpaceAfterCommaEtc
|
28
|
+
|
20
29
|
def kind(token)
|
21
|
-
'comma' if token.type == :
|
30
|
+
'comma' if token.type == :tCOMMA
|
22
31
|
end
|
23
32
|
end
|
24
33
|
|
25
34
|
class SpaceAfterSemicolon < Cop
|
26
35
|
include SpaceAfterCommaEtc
|
36
|
+
|
27
37
|
def kind(token)
|
28
|
-
'semicolon' if token.type == :
|
38
|
+
'semicolon' if token.type == :tSEMI
|
29
39
|
end
|
30
40
|
end
|
31
41
|
|
32
42
|
class SpaceAfterColon < Cop
|
33
43
|
include SpaceAfterCommaEtc
|
44
|
+
|
45
|
+
# The colon following a label will not appear in the token
|
46
|
+
# array. Instad we get a tLABEL token, whose length we use to
|
47
|
+
# calculate where we expect a space.
|
48
|
+
def offset(token)
|
49
|
+
case token.type
|
50
|
+
when :tLABEL then token.text.length + 1
|
51
|
+
when :tCOLON then 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
34
55
|
def kind(token)
|
35
56
|
case token.type
|
36
|
-
when :
|
37
|
-
when :on_op then 'colon' if token.text == ':'
|
57
|
+
when :tLABEL, :tCOLON then 'colon'
|
38
58
|
end
|
39
59
|
end
|
40
60
|
end
|
@@ -3,24 +3,25 @@
|
|
3
3
|
module Rubocop
|
4
4
|
module Cop
|
5
5
|
class SpaceAfterControlKeyword < Cop
|
6
|
-
|
6
|
+
MSG = 'Use space after control keywords.'
|
7
|
+
# elsif and unless are handled by on_if.
|
8
|
+
KEYWORDS = %w(if case when while until)
|
7
9
|
|
8
|
-
|
10
|
+
def on_keyword(node)
|
11
|
+
return if node.loc.is_a?(Parser::Source::Map::Ternary)
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
KEYWORDS.include?(t1.text) && t2.type != :on_sp
|
18
|
-
add_offence(:convention,
|
19
|
-
t1.pos.lineno,
|
20
|
-
ERROR_MESSAGE)
|
21
|
-
end
|
13
|
+
exp = node.loc.expression
|
14
|
+
kw = node.loc.keyword
|
15
|
+
kw_offset = kw.begin_pos - exp.begin_pos
|
16
|
+
if exp.source[kw_offset..-1].start_with?(kw.source + '(')
|
17
|
+
add_offence(:convention, kw.line, MSG)
|
18
|
+
end
|
19
|
+
end
|
22
20
|
|
23
|
-
|
21
|
+
KEYWORDS.each do |keyword|
|
22
|
+
define_method(:"on_#{keyword}") do |node|
|
23
|
+
on_keyword(node)
|
24
|
+
super(node)
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|
@@ -3,44 +3,18 @@
|
|
3
3
|
module Rubocop
|
4
4
|
module Cop
|
5
5
|
class StringLiterals < Cop
|
6
|
-
|
6
|
+
MSG = "Prefer single-quoted strings when you don't need " +
|
7
7
|
'string interpolation or special symbols.'
|
8
8
|
|
9
|
-
def inspect(
|
10
|
-
|
11
|
-
|
12
|
-
state = case [state, t.type]
|
13
|
-
when [:outside, :on_tstring_beg]
|
14
|
-
:double_quote if t.text == '"'
|
9
|
+
def inspect(source, tokens, ast, comments)
|
10
|
+
on_node(:str, ast, :dstr) do |s|
|
11
|
+
text = s.to_a[0]
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
when [:double_quote, :on_embvar]
|
23
|
-
:embedded_variable
|
24
|
-
|
25
|
-
when [:double_quote, :on_tstring_end]
|
26
|
-
add_offence(:convention, t.pos.lineno, ERROR_MESSAGE)
|
27
|
-
:outside
|
28
|
-
|
29
|
-
when [:embedded_expression, :on_rbrace]
|
30
|
-
:valid_double_quote
|
31
|
-
|
32
|
-
when [:embedded_variable, :on_ivar]
|
33
|
-
:valid_double_quote
|
34
|
-
|
35
|
-
when [:embedded_variable, :on_cvar]
|
36
|
-
:valid_double_quote
|
37
|
-
|
38
|
-
when [:embedded_variable, :on_gvar]
|
39
|
-
:valid_double_quote
|
40
|
-
|
41
|
-
when [:valid_double_quote, :on_tstring_end]
|
42
|
-
:outside
|
43
|
-
end || state
|
13
|
+
if text !~ /['\n\t\r]/ && s.loc.expression.source[0] == '"'
|
14
|
+
add_offence(:convention,
|
15
|
+
s.loc.line,
|
16
|
+
MSG)
|
17
|
+
end
|
44
18
|
end
|
45
19
|
end
|
46
20
|
end
|
@@ -1,179 +1,280 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
# rubocop:disable SymbolName
|
4
|
+
|
3
5
|
module Rubocop
|
4
6
|
module Cop
|
5
7
|
module SurroundingSpace
|
6
|
-
def
|
7
|
-
|
8
|
-
|
8
|
+
def space_between?(t1, t2)
|
9
|
+
char_preceding_2nd_token =
|
10
|
+
@source[t2.pos.line - 1][t2.pos.column - 1]
|
11
|
+
if char_preceding_2nd_token == '+' && t1.type != :tPLUS
|
12
|
+
# Special case. A unary plus is not present in the tokens.
|
13
|
+
char_preceding_2nd_token =
|
14
|
+
@source[t2.pos.line - 1][t2.pos.column - 2]
|
9
15
|
end
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def previous_non_space(tokens, ix)
|
16
|
-
tokens[0...ix].reverse.find { |t| !whitespace?(t) }
|
16
|
+
t2.pos.line > t1.pos.line || char_preceding_2nd_token == ' '
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
parent == :command_call && child == :'::'
|
19
|
+
def index_of_first_token(node, tokens)
|
20
|
+
@token_table ||= build_token_table(tokens)
|
21
|
+
b = node.loc.expression.begin
|
22
|
+
@token_table[[b.line, b.column]]
|
24
23
|
end
|
25
24
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
25
|
+
def index_of_last_token(node, tokens)
|
26
|
+
@token_table ||= build_token_table(tokens)
|
27
|
+
e = node.loc.expression.end
|
28
|
+
(0...e.column).to_a.reverse.find do |c|
|
29
|
+
ix = @token_table[[e.line, c]]
|
30
|
+
return ix if ix
|
31
|
+
end
|
29
32
|
end
|
30
33
|
|
31
|
-
|
32
|
-
|
34
|
+
def build_token_table(tokens)
|
35
|
+
table = {}
|
36
|
+
tokens.each_with_index do |t, ix|
|
37
|
+
table[[t.pos.line, t.pos.column]] = ix
|
38
|
+
end
|
39
|
+
table
|
33
40
|
end
|
34
41
|
end
|
35
42
|
|
36
43
|
class SpaceAroundOperators < Cop
|
37
44
|
include SurroundingSpace
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
MSG_MISSING = "Surrounding space missing for operator '%s'."
|
46
|
+
MSG_DETECTED = 'Space around operator ** detected.'
|
47
|
+
|
48
|
+
BINARY_OPERATORS =
|
49
|
+
[:tEQL, :tAMPER2, :tPIPE, :tCARET, :tPLUS, :tMINUS, :tSTAR2,
|
50
|
+
:tDIVIDE, :tPERCENT, :tEH, :tCOLON, :tANDOP, :tOROP, :tMATCH,
|
51
|
+
:tNMATCH, :tEQ, :tNEQ, :tGT, :tRSHFT, :tGEQ, :tLT,
|
52
|
+
:tLSHFT, :tLEQ, :tASSOC, :tEQQ, :tCMP, :tOP_ASGN]
|
53
|
+
|
54
|
+
def inspect(source, tokens, sexp, comments)
|
55
|
+
@source = source
|
56
|
+
positions_not_to_check = get_positions_not_to_check(tokens, sexp)
|
57
|
+
|
58
|
+
tokens.each_cons(3) do |token_before, token, token_after|
|
59
|
+
next if token_before.type == :kDEF # TODO: remove?
|
60
|
+
next if positions_not_to_check.include?(token.pos)
|
61
|
+
|
62
|
+
case token.type
|
63
|
+
when :tPOW
|
64
|
+
if has_space?(token_before, token, token_after)
|
65
|
+
add_offence(:convention, token.pos.line, MSG_DETECTED)
|
47
66
|
end
|
67
|
+
when *BINARY_OPERATORS
|
68
|
+
check_missing_space(token_before, token, token_after)
|
48
69
|
end
|
49
70
|
end
|
50
71
|
end
|
51
72
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
73
|
+
# Returns an array of positions marking the tokens that this cop
|
74
|
+
# should not check, either because the token is not an operator
|
75
|
+
# or because another cop does the check.
|
76
|
+
def get_positions_not_to_check(tokens, sexp)
|
77
|
+
positions_not_to_check = []
|
78
|
+
do_not_check_block_arg_pipes(sexp, positions_not_to_check)
|
79
|
+
do_not_check_param_default(tokens, sexp, positions_not_to_check)
|
80
|
+
do_not_check_class_lshift_self(tokens, sexp, positions_not_to_check)
|
81
|
+
do_not_check_def_things(tokens, sexp, positions_not_to_check)
|
82
|
+
do_not_check_singleton_operator_defs(tokens, sexp,
|
83
|
+
positions_not_to_check)
|
84
|
+
positions_not_to_check
|
85
|
+
end
|
86
|
+
|
87
|
+
def do_not_check_block_arg_pipes(sexp, positions_not_to_check)
|
88
|
+
# each { |a| }
|
89
|
+
# ^ ^
|
90
|
+
on_node(:block, sexp) do |b|
|
91
|
+
on_node(:args, b) do |a|
|
92
|
+
positions_not_to_check << a.loc.begin << a.loc.end if a.loc.begin
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def do_not_check_param_default(tokens, sexp, positions_not_to_check)
|
98
|
+
# func(a, b=nil)
|
99
|
+
# ^
|
100
|
+
on_node(:optarg, sexp) do |optarg|
|
101
|
+
_arg, equals, _value = tokens[index_of_first_token(optarg, tokens),
|
102
|
+
3]
|
103
|
+
positions_not_to_check << equals.pos
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def do_not_check_class_lshift_self(tokens, sexp, positions_not_to_check)
|
108
|
+
# class <<self
|
109
|
+
# ^
|
110
|
+
on_node(:sclass, sexp) do |sclass|
|
111
|
+
ix = index_of_first_token(sclass, tokens)
|
112
|
+
if tokens[ix, 2].map(&:type) == [:kCLASS, :tLSHFT]
|
113
|
+
positions_not_to_check << tokens[ix + 1].pos
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def do_not_check_def_things(tokens, sexp, positions_not_to_check)
|
119
|
+
# def +(other)
|
120
|
+
# ^
|
121
|
+
on_node(:def, sexp) do |def_node|
|
122
|
+
# def each &block
|
123
|
+
# ^
|
124
|
+
# def each *args
|
125
|
+
# ^
|
126
|
+
on_node([:blockarg, :restarg], def_node) do |arg_node|
|
127
|
+
positions_not_to_check << tokens[index_of_first_token(arg_node,
|
128
|
+
tokens)].pos
|
129
|
+
end
|
130
|
+
positions_not_to_check <<
|
131
|
+
tokens[index_of_first_token(def_node, tokens) + 1].pos
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def do_not_check_singleton_operator_defs(tokens, sexp,
|
136
|
+
positions_not_to_check)
|
137
|
+
# def self.===(other)
|
138
|
+
# ^
|
139
|
+
on_node(:defs, sexp) do |defs_node|
|
140
|
+
_receiver, name, _args = *defs_node
|
141
|
+
ix = index_of_first_token(defs_node, tokens)
|
142
|
+
name_token = tokens[ix..-1].find { |t| t.text == name.to_s }
|
143
|
+
positions_not_to_check << name_token.pos
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def check_missing_space(token_before, token, token_after)
|
148
|
+
unless has_space?(token_before, token, token_after)
|
149
|
+
text = token.text.to_s + (token.type == :tOP_ASGN ? '=' : '')
|
150
|
+
add_offence(:convention, token.pos.line, MSG_MISSING % text)
|
58
151
|
end
|
59
152
|
end
|
153
|
+
|
154
|
+
def has_space?(token_before, token, token_after)
|
155
|
+
space_between?(token_before, token) && space_between?(token,
|
156
|
+
token_after)
|
157
|
+
end
|
60
158
|
end
|
61
159
|
|
62
160
|
class SpaceAroundBraces < Cop
|
63
161
|
include SurroundingSpace
|
162
|
+
MSG_LEFT = "Surrounding space missing for '{'."
|
163
|
+
MSG_RIGHT = "Space missing to the left of '}'."
|
164
|
+
|
165
|
+
def inspect(source, tokens, sexp, comments)
|
166
|
+
@source = source
|
167
|
+
positions_not_to_check = get_positions_not_to_check(tokens, sexp)
|
168
|
+
tokens.each_cons(2) do |t1, t2|
|
169
|
+
next if ([t1.pos, t2.pos] - positions_not_to_check).size < 2
|
64
170
|
|
65
|
-
|
171
|
+
type1, type2 = t1.type, t2.type
|
172
|
+
# :tLBRACE in hash literals, :tLCURLY otherwise.
|
173
|
+
next if [:tLCURLY, :tLBRACE].include?(type1) && type2 == :tRCURLY
|
174
|
+
check(t1, t2, MSG_LEFT) if type1 == :tLCURLY || type2 == :tLCURLY
|
175
|
+
check(t1, t2, MSG_RIGHT) if type2 == :tRCURLY
|
176
|
+
end
|
66
177
|
end
|
67
178
|
|
68
|
-
def
|
69
|
-
|
70
|
-
return if grammar_path.last == :hash
|
179
|
+
def get_positions_not_to_check(tokens, sexp)
|
180
|
+
positions_not_to_check = []
|
71
181
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
182
|
+
on_node(:hash, sexp) do |hash|
|
183
|
+
b_ix = index_of_first_token(hash, tokens)
|
184
|
+
e_ix = index_of_last_token(hash, tokens)
|
185
|
+
positions_not_to_check << tokens[b_ix].pos << tokens[e_ix].pos
|
186
|
+
end
|
187
|
+
|
188
|
+
# TODO: Check braces inside string/symbol/regexp/xstr interpolation.
|
189
|
+
on_node([:dstr, :dsym, :regexp, :xstr], sexp) do |s|
|
190
|
+
b_ix = index_of_first_token(s, tokens)
|
191
|
+
e_ix = index_of_last_token(s, tokens)
|
192
|
+
tokens[b_ix..e_ix].each do |t|
|
193
|
+
positions_not_to_check << t.pos if t.type == :tRCURLY
|
83
194
|
end
|
84
195
|
end
|
196
|
+
|
197
|
+
positions_not_to_check
|
198
|
+
end
|
199
|
+
|
200
|
+
def check(t1, t2, msg)
|
201
|
+
unless space_between?(t1, t2)
|
202
|
+
add_offence(:convention, t1.pos.line, msg)
|
203
|
+
end
|
85
204
|
end
|
86
205
|
end
|
87
206
|
|
88
207
|
module SpaceInside
|
89
208
|
include SurroundingSpace
|
209
|
+
MSG = 'Space inside %s detected.'
|
90
210
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
if prev.type == :on_sp
|
101
|
-
prev_ns = previous_non_space(tokens, ix)
|
102
|
-
prev_ns &&
|
103
|
-
prev_ns.pos.lineno == tokens[ix].pos.lineno &&
|
104
|
-
# Avoid double reporting
|
105
|
-
prev_ns.type != paren.left
|
106
|
-
end
|
107
|
-
end
|
108
|
-
if offence_detected
|
109
|
-
add_offence(:convention, t.pos.lineno,
|
110
|
-
"Space inside #{paren.kind} detected.")
|
211
|
+
def inspect(source, tokens, sexp, comments)
|
212
|
+
@source = source
|
213
|
+
left, right, kind = specifics
|
214
|
+
tokens.each_cons(2) do |t1, t2|
|
215
|
+
if t1.type == left || t2.type == right
|
216
|
+
if t2.pos.line == t1.pos.line && space_between?(t1, t2)
|
217
|
+
add_offence(:convention, t1.pos.line, MSG % kind)
|
218
|
+
end
|
219
|
+
end
|
111
220
|
end
|
112
221
|
end
|
113
222
|
end
|
114
223
|
|
115
224
|
class SpaceInsideParens < Cop
|
116
225
|
include SpaceInside
|
117
|
-
|
118
|
-
|
226
|
+
|
227
|
+
def specifics
|
228
|
+
[:tLPAREN2, :tRPAREN, 'parentheses']
|
119
229
|
end
|
120
230
|
end
|
121
231
|
|
122
232
|
class SpaceInsideBrackets < Cop
|
123
233
|
include SpaceInside
|
124
|
-
|
125
|
-
|
234
|
+
|
235
|
+
def specifics
|
236
|
+
[:tLBRACK, :tRBRACK, 'square brackets']
|
126
237
|
end
|
127
238
|
end
|
128
239
|
|
129
240
|
class SpaceInsideHashLiteralBraces < Cop
|
130
241
|
include SurroundingSpace
|
242
|
+
MSG = 'Space inside hash literal braces %s.'
|
131
243
|
|
132
|
-
def
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
def check_unwanted_space(tokens, ix)
|
141
|
-
unless self.class.config['EnforcedStyleIsWithSpaces']
|
142
|
-
grammar_path = @correlations[ix] or return
|
143
|
-
check_space(tokens, ix, grammar_path, 'detected') do |t|
|
144
|
-
whitespace?(t)
|
145
|
-
end
|
244
|
+
def inspect(source, tokens, sexp, comments)
|
245
|
+
@source = source
|
246
|
+
on_node(:hash, sexp) do |hash|
|
247
|
+
b_ix = index_of_first_token(hash, tokens)
|
248
|
+
e_ix = index_of_last_token(hash, tokens)
|
249
|
+
check(tokens[b_ix], tokens[b_ix + 1])
|
250
|
+
check(tokens[e_ix - 1], tokens[e_ix])
|
146
251
|
end
|
147
252
|
end
|
148
253
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
if
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
"Space inside hash literal braces #{word}.")
|
161
|
-
end
|
162
|
-
end
|
254
|
+
def check(t1, t2)
|
255
|
+
types = [t1, t2].map(&:type)
|
256
|
+
braces = [:tLBRACE, :tRCURLY]
|
257
|
+
return if types == braces || (braces - types).size == 2
|
258
|
+
has_space = space_between?(t1, t2)
|
259
|
+
is_offence, word = if self.class.config['EnforcedStyleIsWithSpaces']
|
260
|
+
[!has_space, 'missing']
|
261
|
+
else
|
262
|
+
[has_space, 'detected']
|
263
|
+
end
|
264
|
+
add_offence(:convention, t1.pos.line, MSG % word) if is_offence
|
163
265
|
end
|
164
266
|
end
|
165
267
|
|
166
268
|
class SpaceAroundEqualsInParameterDefault < Cop
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
end
|
269
|
+
include SurroundingSpace
|
270
|
+
MSG = 'Surrounding space missing in default value assignment.'
|
271
|
+
|
272
|
+
def inspect(source, tokens, sexp, comments)
|
273
|
+
@source = source
|
274
|
+
on_node(:optarg, sexp) do |optarg|
|
275
|
+
arg, equals, value = tokens[index_of_first_token(optarg, tokens), 3]
|
276
|
+
unless space_between?(arg, equals) && space_between?(equals, value)
|
277
|
+
add_offence(:convention, equals.pos.line, MSG)
|
177
278
|
end
|
178
279
|
end
|
179
280
|
end
|