rubocop 0.16.0 → 0.17.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.

Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -1
  4. data/CHANGELOG.md +44 -0
  5. data/CONTRIBUTING.md +40 -8
  6. data/Gemfile +6 -0
  7. data/README.md +65 -20
  8. data/Rakefile +0 -1
  9. data/config/default.yml +15 -3
  10. data/config/enabled.yml +143 -109
  11. data/lib/rubocop.rb +45 -26
  12. data/lib/rubocop/cli.rb +26 -27
  13. data/lib/rubocop/config.rb +0 -1
  14. data/lib/rubocop/config_loader.rb +16 -23
  15. data/lib/rubocop/cop/commissioner.rb +2 -7
  16. data/lib/rubocop/cop/cop.rb +24 -51
  17. data/lib/rubocop/cop/ignored_node.rb +31 -0
  18. data/lib/rubocop/cop/lint/ambiguous_operator.rb +50 -0
  19. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +36 -0
  20. data/lib/rubocop/cop/lint/assignment_in_condition.rb +3 -11
  21. data/lib/rubocop/cop/lint/block_alignment.rb +6 -20
  22. data/lib/rubocop/cop/lint/condition_position.rb +52 -0
  23. data/lib/rubocop/cop/lint/else_layout.rb +57 -0
  24. data/lib/rubocop/cop/lint/end_alignment.rb +33 -8
  25. data/lib/rubocop/cop/lint/invalid_character_literal.rb +37 -0
  26. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +2 -4
  27. data/lib/rubocop/cop/lint/syntax.rb +6 -12
  28. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +25 -0
  29. data/lib/rubocop/cop/mixin/array_syntax.rb +20 -0
  30. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +76 -0
  31. data/lib/rubocop/cop/mixin/check_assignment.rb +26 -0
  32. data/lib/rubocop/cop/{check_methods.rb → mixin/check_methods.rb} +0 -0
  33. data/lib/rubocop/cop/mixin/code_length.rb +33 -0
  34. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +53 -0
  35. data/lib/rubocop/cop/mixin/configurable_max.rb +19 -0
  36. data/lib/rubocop/cop/mixin/configurable_naming.rb +45 -0
  37. data/lib/rubocop/cop/{style → mixin}/if_node.rb +0 -0
  38. data/lib/rubocop/cop/mixin/if_then_else.rb +23 -0
  39. data/lib/rubocop/cop/mixin/negative_conditional.rb +24 -0
  40. data/lib/rubocop/cop/mixin/parser_diagnostic.rb +34 -0
  41. data/lib/rubocop/cop/mixin/safe_assignment.rb +19 -0
  42. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +32 -0
  43. data/lib/rubocop/cop/mixin/space_inside.rb +31 -0
  44. data/lib/rubocop/cop/mixin/statement_modifier.rb +59 -0
  45. data/lib/rubocop/cop/mixin/string_help.rb +32 -0
  46. data/lib/rubocop/cop/mixin/surrounding_space.rb +42 -0
  47. data/lib/rubocop/cop/rails/default_scope.rb +3 -1
  48. data/lib/rubocop/cop/style/accessor_method_name.rb +4 -12
  49. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +16 -1
  50. data/lib/rubocop/cop/style/case_indentation.rb +33 -16
  51. data/lib/rubocop/cop/style/character_literal.rb +10 -0
  52. data/lib/rubocop/cop/style/dot_position.rb +23 -6
  53. data/lib/rubocop/cop/style/empty_lines_around_body.rb +5 -5
  54. data/lib/rubocop/cop/style/favor_unless_over_negated_if.rb +1 -32
  55. data/lib/rubocop/cop/style/favor_until_over_negated_while.rb +20 -0
  56. data/lib/rubocop/cop/style/hash_syntax.rb +5 -1
  57. data/lib/rubocop/cop/style/if_unless_modifier.rb +34 -0
  58. data/lib/rubocop/cop/style/if_with_semicolon.rb +1 -1
  59. data/lib/rubocop/cop/style/indentation_consistency.rb +51 -0
  60. data/lib/rubocop/cop/style/indentation_width.rb +0 -26
  61. data/lib/rubocop/cop/style/lambda_call.rb +12 -5
  62. data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -11
  63. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -9
  64. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +22 -0
  65. data/lib/rubocop/cop/style/{ternary_operator.rb → nested_ternary_operator.rb} +0 -15
  66. data/lib/rubocop/cop/style/numeric_literals.rb +30 -2
  67. data/lib/rubocop/cop/style/one_line_conditional.rb +2 -1
  68. data/lib/rubocop/cop/style/parameter_lists.rb +7 -3
  69. data/lib/rubocop/cop/style/parentheses_around_condition.rb +9 -11
  70. data/lib/rubocop/cop/style/predicate_name.rb +4 -12
  71. data/lib/rubocop/cop/style/raise_args.rb +19 -11
  72. data/lib/rubocop/cop/style/regexp_literal.rb +19 -6
  73. data/lib/rubocop/cop/style/space_after_colon.rb +36 -0
  74. data/lib/rubocop/cop/style/space_after_comma.rb +16 -0
  75. data/lib/rubocop/cop/style/space_after_semicolon.rb +16 -0
  76. data/lib/rubocop/cop/style/space_around_block_braces.rb +38 -38
  77. data/lib/rubocop/cop/style/space_around_operators.rb +1 -2
  78. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +6 -2
  79. data/lib/rubocop/cop/style/string_literals.rb +5 -5
  80. data/lib/rubocop/cop/style/trailing_comma.rb +94 -0
  81. data/lib/rubocop/cop/style/unless_else.rb +2 -2
  82. data/lib/rubocop/cop/style/while_until_modifier.rb +32 -0
  83. data/lib/rubocop/cop/style/word_array.rb +9 -1
  84. data/lib/rubocop/cop/util.rb +14 -0
  85. data/lib/rubocop/cop/variable_inspector.rb +11 -6
  86. data/lib/rubocop/cop/variable_inspector/scope.rb +4 -3
  87. data/lib/rubocop/file_inspector.rb +22 -6
  88. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
  89. data/lib/rubocop/formatter/colorizable.rb +37 -0
  90. data/lib/rubocop/formatter/disabled_config_formatter.rb +27 -6
  91. data/lib/rubocop/formatter/progress_formatter.rb +1 -1
  92. data/lib/rubocop/formatter/simple_text_formatter.rb +9 -5
  93. data/lib/rubocop/options.rb +19 -4
  94. data/lib/rubocop/target_finder.rb +4 -0
  95. data/lib/rubocop/version.rb +1 -1
  96. data/rubocop-todo.yml +10 -2
  97. data/rubocop.gemspec +3 -2
  98. data/spec/project_spec.rb +12 -7
  99. data/spec/rubocop/cli_spec.rb +262 -99
  100. data/spec/rubocop/config_loader_spec.rb +5 -5
  101. data/spec/rubocop/config_spec.rb +3 -3
  102. data/spec/rubocop/config_store_spec.rb +12 -11
  103. data/spec/rubocop/cop/commissioner_spec.rb +21 -5
  104. data/spec/rubocop/cop/cop_spec.rb +1 -1
  105. data/spec/rubocop/cop/lint/ambiguous_operator_spec.rb +113 -0
  106. data/spec/rubocop/cop/lint/ambiguous_regexp_literal_spec.rb +35 -0
  107. data/spec/rubocop/cop/lint/block_alignment_spec.rb +2 -2
  108. data/spec/rubocop/cop/lint/condition_position_spec.rb +49 -0
  109. data/spec/rubocop/cop/lint/else_layout_spec.rb +65 -0
  110. data/spec/rubocop/cop/lint/end_alignment_spec.rb +41 -1
  111. data/spec/rubocop/cop/lint/invalid_character_literal_spec.rb +33 -0
  112. data/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb +3 -3
  113. data/spec/rubocop/cop/lint/shadowing_outer_local_variable_spec.rb +12 -12
  114. data/spec/rubocop/cop/lint/syntax_spec.rb +2 -2
  115. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +72 -54
  116. data/spec/rubocop/cop/lint/useless_else_without_rescue_spec.rb +48 -0
  117. data/spec/rubocop/cop/offence_spec.rb +1 -1
  118. data/spec/rubocop/cop/rails/default_scope_spec.rb +6 -0
  119. data/spec/rubocop/cop/rails/output_spec.rb +2 -1
  120. data/spec/rubocop/cop/style/align_hash_spec.rb +9 -9
  121. data/spec/rubocop/cop/style/align_parameters_spec.rb +1 -1
  122. data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +5 -0
  123. data/spec/rubocop/cop/style/case_indentation_spec.rb +53 -2
  124. data/spec/rubocop/cop/style/class_and_module_camel_case_spec.rb +3 -3
  125. data/spec/rubocop/cop/style/documentation_spec.rb +0 -1
  126. data/spec/rubocop/cop/style/dot_position_spec.rb +18 -3
  127. data/spec/rubocop/cop/style/empty_line_between_defs_spec.rb +4 -4
  128. data/spec/rubocop/cop/style/empty_lines_around_body_spec.rb +13 -0
  129. data/spec/rubocop/cop/style/favor_unless_over_negated_if_spec.rb +1 -1
  130. data/spec/rubocop/cop/style/favor_until_over_negated_while_spec.rb +1 -1
  131. data/spec/rubocop/cop/style/hash_syntax_spec.rb +5 -0
  132. data/spec/rubocop/cop/style/{favor_modifier_spec.rb → if_unless_modifier_spec.rb} +4 -111
  133. data/spec/rubocop/cop/style/indentation_consistency_spec.rb +490 -0
  134. data/spec/rubocop/cop/style/indentation_width_spec.rb +19 -91
  135. data/spec/rubocop/cop/style/lambda_call_spec.rb +18 -0
  136. data/spec/rubocop/cop/style/method_called_on_do_end_block_spec.rb +2 -2
  137. data/spec/rubocop/cop/style/method_def_parentheses_spec.rb +35 -1
  138. data/spec/rubocop/cop/style/method_length_spec.rb +1 -0
  139. data/spec/rubocop/cop/style/method_name_spec.rb +27 -5
  140. data/spec/rubocop/cop/style/multiline_block_chain_spec.rb +4 -4
  141. data/spec/rubocop/cop/style/multiline_if_then_spec.rb +2 -2
  142. data/spec/rubocop/cop/style/multiline_ternary_operator_spec.rb +18 -0
  143. data/spec/rubocop/cop/style/{ternary_operator_spec.rb → nested_ternary_operator_spec.rb} +0 -15
  144. data/spec/rubocop/cop/style/numeric_literals_spec.rb +18 -1
  145. data/spec/rubocop/cop/style/one_line_conditional_spec.rb +2 -1
  146. data/spec/rubocop/cop/style/parameter_lists_spec.rb +1 -0
  147. data/spec/rubocop/cop/style/parentheses_around_condition_spec.rb +13 -4
  148. data/spec/rubocop/cop/style/raise_args_spec.rb +22 -0
  149. data/spec/rubocop/cop/style/redundant_self_spec.rb +4 -4
  150. data/spec/rubocop/cop/style/regexp_literal_spec.rb +4 -0
  151. data/spec/rubocop/cop/style/space_after_colon_spec.rb +12 -4
  152. data/spec/rubocop/cop/style/space_after_method_name_spec.rb +2 -2
  153. data/spec/rubocop/cop/style/space_around_block_braces_spec.rb +30 -1
  154. data/spec/rubocop/cop/style/{space_around_equals_in_default_parameter_spec.rb → space_around_equals_in_parameter_default_spec.rb} +0 -0
  155. data/spec/rubocop/cop/style/space_around_operators_spec.rb +2 -1
  156. data/spec/rubocop/cop/style/space_inside_hash_literal_braces_spec.rb +20 -3
  157. data/spec/rubocop/cop/style/string_literals_spec.rb +33 -0
  158. data/spec/rubocop/cop/style/trailing_comma_spec.rb +200 -0
  159. data/spec/rubocop/cop/style/variable_name_spec.rb +27 -3
  160. data/spec/rubocop/cop/style/while_until_modifier_spec.rb +75 -0
  161. data/spec/rubocop/cop/style/word_array_spec.rb +1 -0
  162. data/spec/rubocop/cop/team_spec.rb +1 -1
  163. data/spec/rubocop/cop/variable_inspector/scope_spec.rb +3 -4
  164. data/spec/rubocop/file_inspector_spec.rb +1 -1
  165. data/spec/rubocop/formatter/base_formatter_spec.rb +12 -11
  166. data/spec/rubocop/formatter/colorizable_spec.rb +107 -0
  167. data/spec/rubocop/formatter/disabled_config_formatter_spec.rb +2 -0
  168. data/spec/rubocop/formatter/formatter_set_spec.rb +1 -1
  169. data/spec/rubocop/formatter/json_formatter_spec.rb +4 -3
  170. data/spec/rubocop/formatter/progress_formatter_spec.rb +2 -2
  171. data/spec/rubocop/options_spec.rb +3 -1
  172. data/spec/rubocop/target_finder_spec.rb +13 -11
  173. data/spec/spec_helper.rb +5 -1
  174. data/spec/support/shared_examples.rb +2 -2
  175. data/spec/support/statement_modifier_helper.rb +41 -0
  176. metadata +88 -30
  177. data/lib/rubocop/cop/check_assignment.rb +0 -43
  178. data/lib/rubocop/cop/style/array_syntax.rb +0 -22
  179. data/lib/rubocop/cop/style/autocorrect_alignment.rb +0 -78
  180. data/lib/rubocop/cop/style/code_length.rb +0 -35
  181. data/lib/rubocop/cop/style/configurable_enforced_style.rb +0 -51
  182. data/lib/rubocop/cop/style/configurable_max.rb +0 -17
  183. data/lib/rubocop/cop/style/configurable_naming.rb +0 -41
  184. data/lib/rubocop/cop/style/favor_modifier.rb +0 -118
  185. data/lib/rubocop/cop/style/if_then_else.rb +0 -27
  186. data/lib/rubocop/cop/style/space_after_comma_etc.rb +0 -73
  187. data/lib/rubocop/cop/style/space_inside.rb +0 -33
  188. data/lib/rubocop/cop/style/string_help.rb +0 -30
  189. data/lib/rubocop/cop/style/surrounding_space.rb +0 -44
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for useless `else` in `begin..end` without `rescue`.
7
+ #
8
+ # @example
9
+ # begin
10
+ # do_something
11
+ # else
12
+ # handle_errors # This will never be run.
13
+ # end
14
+ class UselessElseWithoutRescue < Cop
15
+ include ParserDiagnostic
16
+
17
+ private
18
+
19
+ def relevant_diagnostic?(diagnostic)
20
+ diagnostic.reason == :useless_else
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # Common code for ordinary arrays with [] that can be written with %
6
+ # syntax.
7
+ module ArraySyntax
8
+ def array_of?(element_type, node)
9
+ return false unless node.loc.begin && node.loc.begin.is?('[')
10
+
11
+ array_elems = node.children
12
+
13
+ # no need to check empty arrays
14
+ return false unless array_elems && array_elems.size > 1
15
+
16
+ array_elems.all? { |e| e.type == element_type }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,76 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # This module does auto-correction of nodes that should just be moved to
6
+ # the left or to the right, amount being determined by the instance
7
+ # variable @column_delta.
8
+ module AutocorrectAlignment
9
+ def check_alignment(items)
10
+ items.each_cons(2) do |prev, current|
11
+ if current.loc.line > prev.loc.line && start_of_line?(current.loc)
12
+ @column_delta = items.first.loc.column - current.loc.column
13
+ add_offence(current, :expression) if @column_delta != 0
14
+ end
15
+ end
16
+ end
17
+
18
+ def start_of_line?(loc)
19
+ loc.expression.source_line[0...loc.column] =~ /^\s*$/
20
+ end
21
+
22
+ def autocorrect(node)
23
+ # We can't use the instance variable inside the lambda. That would
24
+ # just give each lambda the same reference and they would all get
25
+ # the last value of @column_delta. A local variable fixes the
26
+ # problem.
27
+ column_delta = @column_delta
28
+
29
+ @corrections << lambda do |corrector|
30
+ expr = node.loc.expression
31
+ each_line(expr) do |line_begin_pos, line|
32
+ range = calculate_range(expr, line_begin_pos, column_delta)
33
+ if column_delta > 0
34
+ corrector.insert_before(range, ' ' * column_delta)
35
+ else
36
+ remove(range, corrector)
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def calculate_range(expr, line_begin_pos, column_delta)
43
+ starts_with_space = expr.source_buffer.source[line_begin_pos] =~ / /
44
+ pos_to_remove = if column_delta > 0 || starts_with_space
45
+ line_begin_pos
46
+ else
47
+ line_begin_pos - column_delta.abs
48
+ end
49
+ Parser::Source::Range.new(expr.source_buffer, pos_to_remove,
50
+ pos_to_remove + column_delta.abs)
51
+ end
52
+
53
+ def remove(range, corrector)
54
+ original_stderr = $stderr
55
+ $stderr = StringIO.new # Avoid error messages on console
56
+ corrector.remove(range)
57
+ rescue RuntimeError
58
+ range = Parser::Source::Range.new(range.source_buffer,
59
+ range.begin_pos + 1,
60
+ range.end_pos + 1)
61
+ retry if range.source =~ /^ +$/
62
+ ensure
63
+ $stderr = original_stderr
64
+ end
65
+
66
+ def each_line(expr)
67
+ offset = 0
68
+ expr.source.each_line do |line|
69
+ line_begin_pos = expr.begin_pos + offset
70
+ yield line_begin_pos, line
71
+ offset += line.length
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # Common functionality for checking assignment nodes.
6
+ module CheckAssignment
7
+ TYPES = Util::ASGN_NODES - [:casgn, :op_asgn]
8
+ TYPES.each do |type|
9
+ define_method("on_#{type}") do |node|
10
+ _lhs, rhs = *node
11
+ check_assignment(node, rhs)
12
+ end
13
+ end
14
+
15
+ def on_casgn(node)
16
+ _scope, _lhs, rhs = *node
17
+ check_assignment(node, rhs)
18
+ end
19
+
20
+ def on_op_asgn(node)
21
+ _lhs, _op, rhs = *node
22
+ check_assignment(node, rhs)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # Common functionality for checking length of code segments.
6
+ module CodeLength
7
+ include ConfigurableMax
8
+
9
+ def max_length
10
+ cop_config['Max']
11
+ end
12
+
13
+ def count_comments?
14
+ cop_config['CountComments']
15
+ end
16
+
17
+ def check(node, *_)
18
+ length = code_length(node)
19
+ if length > max_length
20
+ add_offence(node, :keyword, sprintf(message, length,
21
+ max_length)) do
22
+ self.max = length
23
+ end
24
+ end
25
+ end
26
+
27
+ # Returns true for lines that shall not be included in the count.
28
+ def irrelevant_line(source_line)
29
+ source_line.blank? || !count_comments? && comment_line?(source_line)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # Handles `EnforcedStyle` configuration parameters.
6
+ module ConfigurableEnforcedStyle
7
+ def opposite_style_detected
8
+ self.config_to_allow_offences ||=
9
+ { parameter_name => alternative_style.to_s }
10
+ both_styles_detected if config_to_allow_offences['Enabled']
11
+ end
12
+
13
+ def correct_style_detected
14
+ # Enabled:true indicates, later when the opposite style is detected,
15
+ # that the correct style is used somewhere.
16
+ self.config_to_allow_offences ||= { 'Enabled' => true }
17
+ both_styles_detected if config_to_allow_offences[parameter_name]
18
+ end
19
+
20
+ def both_styles_detected
21
+ # Both correct and opposite styles exist.
22
+ self.config_to_allow_offences = { 'Enabled' => false }
23
+ end
24
+
25
+ def unrecognized_style_detected
26
+ # All we can do is to disable.
27
+ self.config_to_allow_offences = { 'Enabled' => false }
28
+ end
29
+
30
+ def style
31
+ s = cop_config[parameter_name]
32
+ if cop_config['SupportedStyles'].include?(s)
33
+ s.to_sym
34
+ else
35
+ fail "Unknown style #{s} selected!"
36
+ end
37
+ end
38
+
39
+ def alternative_style
40
+ a = cop_config['SupportedStyles'].map(&:to_sym)
41
+ if a.size != 2
42
+ fail 'alternative_style can only be used when there are exactly ' +
43
+ '2 SupportedStyles'
44
+ end
45
+ style == a.first ? a.last : a.first
46
+ end
47
+
48
+ def parameter_name
49
+ 'EnforcedStyle'
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # Handles `Max` configuration parameters, especially setting them to an
6
+ # appropriate value with --auto-gen-config.
7
+ module ConfigurableMax
8
+ def max=(value)
9
+ cfg = self.config_to_allow_offences ||= {}
10
+ value = [cfg[parameter_name], value].max if cfg[parameter_name]
11
+ cfg[parameter_name] = value
12
+ end
13
+
14
+ def parameter_name
15
+ 'Max'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # This module provides functionality for checking if names match the
6
+ # configured EnforcedStyle.
7
+ module ConfigurableNaming
8
+ include ConfigurableEnforcedStyle
9
+
10
+ SNAKE_CASE = /^@?[\da-z_]+[!?=]?$/
11
+ CAMEL_CASE = /^@?[a-z][\da-zA-Z]+[!?=]?$/
12
+
13
+ def check(node, range)
14
+ return unless range
15
+
16
+ name = range.source.to_sym
17
+ return if operator?(name)
18
+
19
+ if matches_config?(name)
20
+ correct_style_detected
21
+ else
22
+ add_offence(node, range, message(style)) do
23
+ opposite_style_detected
24
+ end
25
+ end
26
+ end
27
+
28
+ def matches_config?(name)
29
+ name =~ (style == :snake_case ? SNAKE_CASE : CAMEL_CASE)
30
+ end
31
+
32
+ # Returns a range containing the method name after the given regexp and
33
+ # a dot.
34
+ def after_dot(node, method_name_length, regexp)
35
+ expr = node.loc.expression
36
+ match = /\A#{regexp}\s*\.\s*/.match(expr.source)
37
+ return unless match
38
+ offset = match[0].length
39
+ begin_pos = expr.begin_pos + offset
40
+ Parser::Source::Range.new(expr.source_buffer, begin_pos,
41
+ begin_pos + method_name_length)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # Common functionality for cops checking if and unless statements.
6
+ module IfThenElse
7
+ def on_if(node)
8
+ check(node)
9
+ end
10
+
11
+ def on_unless(node)
12
+ check(node)
13
+ end
14
+
15
+ def check(node)
16
+ # We won't check modifier or ternary conditionals.
17
+ return unless node.loc.expression.source =~ /\A(if|unless)\b/
18
+ return unless offending_line(node)
19
+ add_offence(node, :expression, error_message(node))
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # Some common code shared between FavorUnlessOverNegatedIf and
6
+ # FavorUntilOverNegatedWhile.
7
+ module NegativeConditional
8
+ def check(node)
9
+ condition, _body, _rest = *node
10
+
11
+ # Look at last expression of contents if there's a parenthesis
12
+ # around condition.
13
+ condition = condition.children.last while condition.type == :begin
14
+
15
+ if condition.type == :send
16
+ _object, method = *condition
17
+ if method == :! && !(node.loc.respond_to?(:else) && node.loc.else)
18
+ add_offence(node, :expression, error_message)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # Common functionality for cops which processes Parser's diagnostics.
6
+ # This mixin requires its user class to define `#relevant_diagnostic?`.
7
+ #
8
+ # def relevant_diagnostic?(diagnostic)
9
+ # diagnostic.reason == :my_interested_diagnostic_type
10
+ # end
11
+ #
12
+ # If you want to use an alternative offence message rather than the one in
13
+ # Parser's diagnostic, define `#alternative_message`.
14
+ #
15
+ # def alternative_message(diagnostic)
16
+ # 'My custom message'
17
+ # end
18
+ module ParserDiagnostic
19
+ def investigate(processed_source)
20
+ processed_source.diagnostics.each do |d|
21
+ next unless relevant_diagnostic?(d)
22
+
23
+ message = if respond_to?(:alternative_message, true)
24
+ alternative_message(d)
25
+ else
26
+ d.message.capitalize
27
+ end
28
+
29
+ add_offence(nil, d.location, message, d.level)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # Common functionality for safe assignment. By safe assignment we mean
6
+ # putting parentheses around an assignment to indicate "I know I'm using an
7
+ # assignment as a condition. It's not a mistake."
8
+ module SafeAssignment
9
+ def safe_assignment?(node)
10
+ node.type == :begin && node.children.size == 1 &&
11
+ Util::EQUALS_ASGN_NODES.include?(node.children[0].type)
12
+ end
13
+
14
+ def safe_assignment_allowed?
15
+ cop_config['AllowSafeAssignment']
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # Common functionality for cops checking for missing space after
6
+ # punctuation.
7
+ module SpaceAfterPunctuation
8
+ MSG = 'Space missing after %s.'
9
+
10
+ def investigate(processed_source)
11
+ processed_source.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(t1, t1.pos, sprintf(MSG, kind(t1)))
15
+ end
16
+ end
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
24
+
25
+ def autocorrect(token)
26
+ @corrections << lambda do |corrector|
27
+ corrector.insert_after(token.pos, ' ')
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end