rubocop 0.4.0 → 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 +7 -0
- data/.gitignore +50 -0
- data/.rubocop.yml +5 -127
- data/.travis.yml +7 -1
- data/CHANGELOG.md +157 -0
- data/CONTRIBUTING.md +13 -6
- data/Gemfile +3 -8
- data/README.md +160 -9
- data/Rakefile +3 -17
- data/bin/rubocop +16 -10
- data/config/default.yml +46 -0
- data/config/disabled.yml +5 -0
- data/config/enabled.yml +322 -0
- data/lib/rubocop/cli.rb +248 -93
- data/lib/rubocop/config.rb +205 -0
- data/lib/rubocop/config_store.rb +37 -0
- data/lib/rubocop/cop/access_control.rb +41 -0
- data/lib/rubocop/cop/alias.rb +17 -0
- data/lib/rubocop/cop/align_parameters.rb +20 -95
- data/lib/rubocop/cop/and_or.rb +26 -0
- data/lib/rubocop/cop/ascii_comments.rb +13 -0
- data/lib/rubocop/cop/ascii_identifiers.rb +19 -0
- data/lib/rubocop/cop/avoid_class_vars.rb +15 -0
- data/lib/rubocop/cop/avoid_for.rb +17 -0
- data/lib/rubocop/cop/avoid_global_vars.rb +61 -0
- data/lib/rubocop/cop/avoid_perl_backrefs.rb +17 -0
- data/lib/rubocop/cop/avoid_perlisms.rb +47 -0
- data/lib/rubocop/cop/block_comments.rb +15 -0
- data/lib/rubocop/cop/blocks.rb +11 -47
- data/lib/rubocop/cop/case_indentation.rb +22 -0
- data/lib/rubocop/cop/class_and_module_camel_case.rb +20 -11
- data/lib/rubocop/cop/class_methods.rb +15 -0
- data/lib/rubocop/cop/collection_methods.rb +16 -16
- data/lib/rubocop/cop/colon_method_call.rb +20 -0
- data/lib/rubocop/cop/constant_name.rb +24 -0
- data/lib/rubocop/cop/cop.rb +34 -47
- data/lib/rubocop/cop/def_parentheses.rb +43 -35
- data/lib/rubocop/cop/empty_line_between_defs.rb +22 -0
- data/lib/rubocop/cop/empty_lines.rb +21 -13
- 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 +19 -0
- data/lib/rubocop/cop/eval.rb +19 -0
- data/lib/rubocop/cop/favor_join.rb +22 -0
- data/lib/rubocop/cop/favor_modifier.rb +38 -48
- data/lib/rubocop/cop/favor_percent_r.rb +19 -0
- data/lib/rubocop/cop/favor_sprintf.rb +21 -0
- data/lib/rubocop/cop/favor_unless_over_negated_if.rb +19 -17
- data/lib/rubocop/cop/handle_exceptions.rb +17 -0
- 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 +17 -0
- data/lib/rubocop/cop/line_continuation.rb +15 -0
- data/lib/rubocop/cop/line_length.rb +4 -4
- data/lib/rubocop/cop/loop.rb +33 -0
- data/lib/rubocop/cop/method_and_variable_snake_case.rb +41 -17
- data/lib/rubocop/cop/method_length.rb +52 -0
- data/lib/rubocop/cop/new_lambda_literal.rb +8 -6
- data/lib/rubocop/cop/not.rb +21 -0
- data/lib/rubocop/cop/numeric_literals.rb +9 -7
- data/lib/rubocop/cop/offence.rb +12 -1
- data/lib/rubocop/cop/op_method.rb +26 -0
- 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 +19 -0
- data/lib/rubocop/cop/reduce_arguments.rb +29 -0
- data/lib/rubocop/cop/rescue_exception.rb +26 -0
- data/lib/rubocop/cop/rescue_modifier.rb +17 -0
- data/lib/rubocop/cop/semicolon.rb +31 -0
- data/lib/rubocop/cop/single_line_methods.rb +44 -0
- data/lib/rubocop/cop/space_after_comma_etc.rb +30 -10
- data/lib/rubocop/cop/space_after_control_keyword.rb +29 -0
- data/lib/rubocop/cop/string_literals.rb +9 -23
- data/lib/rubocop/cop/surrounding_space.rb +223 -83
- data/lib/rubocop/cop/symbol_array.rb +31 -0
- data/lib/rubocop/cop/symbol_name.rb +23 -0
- data/lib/rubocop/cop/syntax.rb +35 -5
- 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 +26 -0
- data/lib/rubocop/cop/unless_else.rb +11 -7
- data/lib/rubocop/cop/util.rb +26 -0
- data/lib/rubocop/cop/variable_interpolation.rb +29 -0
- data/lib/rubocop/cop/when_then.rb +6 -14
- data/lib/rubocop/cop/word_array.rb +37 -0
- data/lib/rubocop/report/emacs_style.rb +2 -2
- data/lib/rubocop/report/plain_text.rb +1 -1
- data/lib/rubocop/version.rb +3 -1
- data/lib/rubocop.rb +48 -8
- data/rubocop.gemspec +32 -151
- data/spec/project_spec.rb +27 -0
- data/spec/rubocop/cli_spec.rb +573 -200
- data/spec/rubocop/config_spec.rb +409 -0
- data/spec/rubocop/config_store_spec.rb +66 -0
- data/spec/rubocop/cops/access_control_spec.rb +129 -0
- data/spec/rubocop/cops/alias_spec.rb +39 -0
- data/spec/rubocop/cops/align_parameters_spec.rb +66 -70
- data/spec/rubocop/cops/and_or_spec.rb +37 -0
- data/spec/rubocop/cops/ascii_comments_spec.rb +26 -0
- data/spec/rubocop/cops/ascii_identifiers_spec.rb +26 -0
- data/spec/rubocop/cops/avoid_class_vars_spec.rb +25 -0
- data/spec/rubocop/cops/avoid_for_spec.rb +35 -0
- data/spec/rubocop/cops/avoid_global_vars_spec.rb +32 -0
- data/spec/rubocop/cops/avoid_perl_backrefs_spec.rb +18 -0
- data/spec/rubocop/cops/avoid_perlisms_spec.rb +44 -0
- data/spec/rubocop/cops/block_comments_spec.rb +25 -0
- data/spec/rubocop/cops/blocks_spec.rb +33 -0
- data/spec/rubocop/cops/{indentation_spec.rb → case_indentation_spec.rb} +7 -7
- data/spec/rubocop/cops/class_and_module_camel_case_spec.rb +15 -5
- data/spec/rubocop/cops/class_methods_spec.rb +49 -0
- data/spec/rubocop/cops/collection_methods_spec.rb +9 -4
- data/spec/rubocop/cops/colon_method_call_spec.rb +53 -0
- 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 +83 -0
- data/spec/rubocop/cops/empty_lines_spec.rb +14 -59
- data/spec/rubocop/cops/empty_literal_spec.rb +90 -0
- data/spec/rubocop/cops/encoding_spec.rb +11 -11
- data/spec/rubocop/cops/end_of_line_spec.rb +2 -2
- data/spec/rubocop/cops/ensure_return_spec.rb +35 -0
- data/spec/rubocop/cops/eval_spec.rb +39 -0
- data/spec/rubocop/cops/favor_join_spec.rb +35 -0
- data/spec/rubocop/cops/favor_modifier_spec.rb +16 -14
- data/spec/rubocop/cops/favor_percent_r_spec.rb +29 -0
- data/spec/rubocop/cops/favor_sprintf_spec.rb +51 -0
- 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 +34 -0
- 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 +54 -0
- data/spec/rubocop/cops/line_continuation_spec.rb +24 -0
- data/spec/rubocop/cops/line_length_spec.rb +3 -2
- data/spec/rubocop/cops/loop_spec.rb +31 -0
- data/spec/rubocop/cops/method_and_variable_snake_case_spec.rb +55 -9
- data/spec/rubocop/cops/method_length_spec.rb +147 -0
- data/spec/rubocop/cops/multiline_if_then_spec.rb +15 -15
- data/spec/rubocop/cops/new_lambda_literal_spec.rb +5 -6
- data/spec/rubocop/cops/not_spec.rb +31 -0
- data/spec/rubocop/cops/numeric_literals_spec.rb +13 -13
- data/spec/rubocop/cops/offence_spec.rb +13 -0
- data/spec/rubocop/cops/one_line_conditional_spec.rb +1 -1
- data/spec/rubocop/cops/op_method_spec.rb +78 -0
- 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 +29 -0
- data/spec/rubocop/cops/reduce_arguments_spec.rb +57 -0
- data/spec/rubocop/cops/rescue_exception_spec.rb +125 -0
- data/spec/rubocop/cops/rescue_modifier_spec.rb +37 -0
- data/spec/rubocop/cops/semicolon_spec.rb +88 -0
- data/spec/rubocop/cops/single_line_methods_spec.rb +50 -0
- 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 +67 -0
- data/spec/rubocop/cops/space_after_semicolon_spec.rb +6 -1
- data/spec/rubocop/cops/space_around_braces_spec.rb +18 -3
- data/spec/rubocop/cops/space_around_equals_in_default_parameter_spec.rb +12 -2
- data/spec/rubocop/cops/space_around_operators_spec.rb +88 -26
- data/spec/rubocop/cops/space_inside_brackets_spec.rb +13 -7
- data/spec/rubocop/cops/space_inside_hash_literal_braces_spec.rb +79 -0
- data/spec/rubocop/cops/space_inside_parens_spec.rb +7 -3
- data/spec/rubocop/cops/string_literals_spec.rb +21 -6
- data/spec/rubocop/cops/symbol_array_spec.rb +41 -0
- data/spec/rubocop/cops/symbol_name_spec.rb +119 -0
- data/spec/rubocop/cops/syntax_spec.rb +28 -5
- 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 +329 -0
- data/spec/rubocop/cops/unless_else_spec.rb +8 -8
- data/spec/rubocop/cops/variable_interpolation_spec.rb +49 -0
- data/spec/rubocop/cops/when_then_spec.rb +14 -14
- data/spec/rubocop/cops/word_array_spec.rb +47 -0
- data/spec/spec_helper.rb +30 -9
- data/spec/support/file_helper.rb +21 -0
- data/spec/support/isolated_environment.rb +27 -0
- metadata +235 -76
- data/.document +0 -5
- data/Gemfile.lock +0 -41
- data/VERSION +0 -1
- data/lib/rubocop/cop/ampersands_pipes_vs_and_or.rb +0 -25
- data/lib/rubocop/cop/grammar.rb +0 -135
- data/lib/rubocop/cop/indentation.rb +0 -44
- data/spec/rubocop/cops/ampersands_pipes_vs_and_or_spec.rb +0 -57
- data/spec/rubocop/cops/grammar_spec.rb +0 -71
- data/spec/rubocop/cops/multiline_blocks_spec.rb +0 -24
- data/spec/rubocop/cops/single_line_blocks_spec.rb +0 -22
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
class SingleLineMethods < Cop
|
6
|
+
MSG = 'Avoid single-line method definitions.'
|
7
|
+
|
8
|
+
def allow_empty?
|
9
|
+
SingleLineMethods.config['AllowIfMethodIsEmpty']
|
10
|
+
end
|
11
|
+
|
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
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
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)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
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(
|
9
|
-
tokens.
|
10
|
-
|
11
|
-
|
12
|
-
add_offence(:convention,
|
10
|
+
def inspect(source, tokens, ast, comments)
|
11
|
+
tokens.each_cons(2) do |t1, t2|
|
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
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
class SpaceAfterControlKeyword < Cop
|
6
|
+
MSG = 'Use space after control keywords.'
|
7
|
+
# elsif and unless are handled by on_if.
|
8
|
+
KEYWORDS = %w(if case when while until)
|
9
|
+
|
10
|
+
def on_keyword(node)
|
11
|
+
return if node.loc.is_a?(Parser::Source::Map::Ternary)
|
12
|
+
|
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
|
20
|
+
|
21
|
+
KEYWORDS.each do |keyword|
|
22
|
+
define_method(:"on_#{keyword}") do |node|
|
23
|
+
on_keyword(node)
|
24
|
+
super(node)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -3,32 +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_tstring_end]
|
23
|
-
add_offence(:convention, t.pos.lineno, ERROR_MESSAGE)
|
24
|
-
:outside
|
25
|
-
|
26
|
-
when [:embedded_expression, :on_rbrace]
|
27
|
-
:valid_double_quote
|
28
|
-
|
29
|
-
when [:valid_double_quote, :on_tstring_end]
|
30
|
-
:outside
|
31
|
-
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
|
32
18
|
end
|
33
19
|
end
|
34
20
|
end
|
@@ -1,140 +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| not 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)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
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
|
48
114
|
end
|
49
115
|
end
|
50
116
|
end
|
51
117
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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 '}'."
|
64
164
|
|
65
|
-
def
|
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
|
170
|
+
|
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
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
179
|
+
def get_positions_not_to_check(tokens, sexp)
|
180
|
+
positions_not_to_check = []
|
181
|
+
|
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
|
80
194
|
end
|
81
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
|
82
204
|
end
|
83
205
|
end
|
84
206
|
|
85
207
|
module SpaceInside
|
86
208
|
include SurroundingSpace
|
209
|
+
MSG = 'Space inside %s detected.'
|
87
210
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
if prev.type == :on_sp
|
98
|
-
prev_ns = previous_non_space(tokens, ix)
|
99
|
-
prev_ns &&
|
100
|
-
prev_ns.pos.lineno == tokens[ix].pos.lineno &&
|
101
|
-
# Avoid double reporting
|
102
|
-
prev_ns.type != paren.left
|
103
|
-
end
|
104
|
-
end
|
105
|
-
if offence_detected
|
106
|
-
add_offence(:convention, t.pos.lineno,
|
107
|
-
"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
|
108
220
|
end
|
109
221
|
end
|
110
222
|
end
|
111
223
|
|
112
224
|
class SpaceInsideParens < Cop
|
113
225
|
include SpaceInside
|
114
|
-
|
115
|
-
|
226
|
+
|
227
|
+
def specifics
|
228
|
+
[:tLPAREN2, :tRPAREN, 'parentheses']
|
116
229
|
end
|
117
230
|
end
|
118
231
|
|
119
232
|
class SpaceInsideBrackets < Cop
|
120
233
|
include SpaceInside
|
121
|
-
|
122
|
-
|
234
|
+
|
235
|
+
def specifics
|
236
|
+
[:tLBRACK, :tRBRACK, 'square brackets']
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
class SpaceInsideHashLiteralBraces < Cop
|
241
|
+
include SurroundingSpace
|
242
|
+
MSG = 'Space inside hash literal braces %s.'
|
243
|
+
|
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])
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
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
|
123
265
|
end
|
124
266
|
end
|
125
267
|
|
126
268
|
class SpaceAroundEqualsInParameterDefault < Cop
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
end
|
137
|
-
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)
|
138
278
|
end
|
139
279
|
end
|
140
280
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
class SymbolArray < Cop
|
6
|
+
MSG = 'Use %i or %I for array of symbols.'
|
7
|
+
|
8
|
+
def inspect(source, tokens, ast, comments)
|
9
|
+
# %i and %I were introduced in Ruby 2.0
|
10
|
+
unless RUBY_VERSION < '2.0.0'
|
11
|
+
on_node(:array, ast) do |s|
|
12
|
+
next unless s.loc.begin && s.loc.begin.source == '['
|
13
|
+
|
14
|
+
array_elems = s.children
|
15
|
+
|
16
|
+
# no need to check empty arrays
|
17
|
+
next unless array_elems && array_elems.size > 1
|
18
|
+
|
19
|
+
symbol_array = array_elems.all? { |e| e.type == :sym }
|
20
|
+
|
21
|
+
if symbol_array
|
22
|
+
add_offence(:convention,
|
23
|
+
s.loc.line,
|
24
|
+
MSG)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
class SymbolName < Cop
|
6
|
+
MSG = 'Use snake_case for symbols.'
|
7
|
+
SNAKE_CASE = /^[\da-z_]+[!?=]?$/
|
8
|
+
CAMEL_CASE = /^[A-Z][A-Za-z\d]*$/
|
9
|
+
|
10
|
+
def allow_camel_case?
|
11
|
+
self.class.config['AllowCamelCase']
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_sym(node)
|
15
|
+
sym_name = node.to_a[0]
|
16
|
+
return unless sym_name =~ /^[a-zA-Z]/
|
17
|
+
return if sym_name =~ SNAKE_CASE
|
18
|
+
return if allow_camel_case? && sym_name =~ CAMEL_CASE
|
19
|
+
add_offence(:convention, node.loc.line, MSG)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/rubocop/cop/syntax.rb
CHANGED
@@ -5,13 +5,43 @@ require 'open3'
|
|
5
5
|
module Rubocop
|
6
6
|
module Cop
|
7
7
|
class Syntax < Cop
|
8
|
-
def
|
9
|
-
|
10
|
-
|
8
|
+
def inspect_file(file)
|
9
|
+
# Starting JRuby processes would be extremely slow
|
10
|
+
# We need to check if rbx returns nice warning messages
|
11
|
+
return unless RUBY_ENGINE == 'ruby'
|
12
|
+
|
13
|
+
stderr = nil
|
14
|
+
|
15
|
+
# it's extremely important to run the syntax check in a
|
16
|
+
# clean environment - otherwise it will be extremely slow
|
17
|
+
if defined? Bundler
|
18
|
+
Bundler.with_clean_env do
|
19
|
+
_, stderr, _ = Open3.capture3("ruby -wc #{file}")
|
20
|
+
end
|
21
|
+
else
|
22
|
+
_, stderr, _ = Open3.capture3("ruby -wc #{file}")
|
23
|
+
end
|
11
24
|
|
12
25
|
stderr.each_line do |line|
|
13
|
-
|
14
|
-
|
26
|
+
# discard lines that are not containing relevant info
|
27
|
+
if line =~ /.+:(\d+): (.+)/
|
28
|
+
# Assignment to unused variables beginning with underscore
|
29
|
+
# is reported by Ruby 1.9, but not 2.0. Make 1.9 behave
|
30
|
+
# like 2.0.
|
31
|
+
unless line =~ /assigned but unused variable - _\w+/
|
32
|
+
line_no, severity, message = process_line(line)
|
33
|
+
add_offence(severity, line_no, message)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def process_line(line)
|
40
|
+
line_no, message = line.match(/.+:(\d+): (.+)/).captures
|
41
|
+
if message.start_with?('warning: ')
|
42
|
+
[line_no.to_i, :warning, message.sub(/warning: /, '').capitalize]
|
43
|
+
else
|
44
|
+
[line_no.to_i, :error, message.capitalize]
|
15
45
|
end
|
16
46
|
end
|
17
47
|
end
|
data/lib/rubocop/cop/tab.rb
CHANGED
@@ -3,11 +3,11 @@
|
|
3
3
|
module Rubocop
|
4
4
|
module Cop
|
5
5
|
class Tab < Cop
|
6
|
-
|
6
|
+
MSG = 'Tab detected.'
|
7
7
|
|
8
|
-
def inspect(
|
8
|
+
def inspect(source, tokens, ast, comments)
|
9
9
|
source.each_with_index do |line, index|
|
10
|
-
add_offence(:convention, index + 1,
|
10
|
+
add_offence(:convention, index + 1, MSG) if line =~ /^ *\t/
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|