rubocop 0.20.1 → 0.21.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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -0
  3. data/README.md +16 -4
  4. data/config/default.yml +37 -10
  5. data/config/enabled.yml +25 -7
  6. data/lib/rubocop.rb +15 -19
  7. data/lib/rubocop/cli.rb +2 -2
  8. data/lib/rubocop/config.rb +40 -3
  9. data/lib/rubocop/config_loader.rb +6 -37
  10. data/lib/rubocop/config_store.rb +0 -1
  11. data/lib/rubocop/cop/commissioner.rb +12 -9
  12. data/lib/rubocop/cop/cop.rb +17 -5
  13. data/lib/rubocop/cop/force.rb +41 -0
  14. data/lib/rubocop/cop/ignored_node.rb +10 -10
  15. data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
  16. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +2 -2
  17. data/lib/rubocop/cop/lint/block_alignment.rb +2 -2
  18. data/lib/rubocop/cop/lint/condition_position.rb +2 -0
  19. data/lib/rubocop/cop/lint/debugger.rb +17 -3
  20. data/lib/rubocop/cop/lint/end_alignment.rb +3 -11
  21. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  22. data/lib/rubocop/cop/lint/rescue_exception.rb +11 -0
  23. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +4 -6
  24. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +39 -0
  25. data/lib/rubocop/cop/lint/unused_block_argument.rb +81 -0
  26. data/lib/rubocop/cop/lint/unused_method_argument.rb +52 -0
  27. data/lib/rubocop/cop/lint/useless_assignment.rb +6 -8
  28. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +6 -0
  29. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  30. data/lib/rubocop/cop/lint/void.rb +1 -1
  31. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +2 -2
  32. data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +7 -3
  33. data/lib/rubocop/cop/mixin/check_assignment.rb +11 -0
  34. data/lib/rubocop/cop/mixin/check_methods.rb +12 -0
  35. data/lib/rubocop/cop/mixin/percent_literal.rb +26 -0
  36. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +2 -2
  37. data/lib/rubocop/cop/mixin/string_help.rb +0 -4
  38. data/lib/rubocop/cop/rails/delegate.rb +109 -0
  39. data/lib/rubocop/cop/style/align_hash.rb +3 -3
  40. data/lib/rubocop/cop/style/class_and_module_children.rb +2 -2
  41. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  42. data/lib/rubocop/cop/style/dot_position.rb +1 -1
  43. data/lib/rubocop/cop/style/encoding.rb +44 -16
  44. data/lib/rubocop/cop/style/indentation_width.rb +29 -19
  45. data/lib/rubocop/cop/style/lambda_call.rb +1 -1
  46. data/lib/rubocop/cop/style/line_end_concatenation.rb +1 -1
  47. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +3 -21
  48. data/lib/rubocop/cop/style/predicate_name.rb +1 -1
  49. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  50. data/lib/rubocop/cop/style/redundant_begin.rb +18 -2
  51. data/lib/rubocop/cop/style/redundant_self.rb +2 -2
  52. data/lib/rubocop/cop/style/regexp_literal.rb +29 -37
  53. data/lib/rubocop/cop/style/space_after_method_name.rb +1 -1
  54. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  55. data/lib/rubocop/cop/style/trailing_blank_lines.rb +37 -23
  56. data/lib/rubocop/cop/style/trailing_comma.rb +2 -3
  57. data/lib/rubocop/cop/style/trivial_accessors.rb +40 -4
  58. data/lib/rubocop/cop/style/unneeded_capital_w.rb +29 -0
  59. data/lib/rubocop/cop/team.rb +10 -2
  60. data/lib/rubocop/cop/util.rb +2 -2
  61. data/lib/rubocop/cop/{variable_inspector.rb → variable_force.rb} +45 -37
  62. data/lib/rubocop/cop/{variable_inspector → variable_force}/assignment.rb +1 -1
  63. data/lib/rubocop/cop/{variable_inspector → variable_force}/locatable.rb +1 -1
  64. data/lib/rubocop/cop/{variable_inspector → variable_force}/reference.rb +13 -1
  65. data/lib/rubocop/cop/{variable_inspector → variable_force}/scope.rb +9 -1
  66. data/lib/rubocop/cop/{variable_inspector → variable_force}/variable.rb +14 -4
  67. data/lib/rubocop/cop/{variable_inspector → variable_force}/variable_table.rb +1 -1
  68. data/lib/rubocop/file_inspector.rb +3 -1
  69. data/lib/rubocop/formatter/base_formatter.rb +1 -1
  70. data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -2
  71. data/lib/rubocop/formatter/disabled_lines_formatter.rb +2 -2
  72. data/lib/rubocop/formatter/offense_count_formatter.rb +11 -10
  73. data/lib/rubocop/formatter/progress_formatter.rb +2 -2
  74. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  75. data/lib/rubocop/options.rb +74 -58
  76. data/lib/rubocop/path_util.rb +17 -2
  77. data/lib/rubocop/rake_task.rb +23 -5
  78. data/lib/rubocop/version.rb +1 -1
  79. data/relnotes/v0.21.0.md +45 -0
  80. data/rubocop-todo.yml +6 -6
  81. data/rubocop.gemspec +1 -1
  82. data/spec/rubocop/cli_spec.rb +170 -59
  83. data/spec/rubocop/config_spec.rb +48 -3
  84. data/spec/rubocop/config_store_spec.rb +3 -3
  85. data/spec/rubocop/cop/commissioner_spec.rb +9 -7
  86. data/spec/rubocop/cop/cop_spec.rb +0 -2
  87. data/spec/rubocop/cop/force_spec.rb +29 -0
  88. data/spec/rubocop/cop/lint/ambiguous_operator_spec.rb +2 -2
  89. data/spec/rubocop/cop/lint/ambiguous_regexp_literal_spec.rb +1 -1
  90. data/spec/rubocop/cop/lint/block_alignment_spec.rb +24 -24
  91. data/spec/rubocop/cop/lint/condition_position_spec.rb +7 -5
  92. data/spec/rubocop/cop/lint/debugger_spec.rb +26 -9
  93. data/spec/rubocop/cop/lint/end_alignment_spec.rb +6 -3
  94. data/spec/rubocop/cop/lint/invalid_character_literal_spec.rb +7 -6
  95. data/spec/rubocop/cop/lint/rescue_exception_spec.rb +36 -0
  96. data/spec/rubocop/cop/lint/shadowing_outer_local_variable_spec.rb +4 -4
  97. data/spec/rubocop/cop/lint/underscore_prefixed_variable_name_spec.rb +179 -0
  98. data/spec/rubocop/cop/lint/unused_block_argument_spec.rb +147 -0
  99. data/spec/rubocop/cop/lint/unused_method_argument_spec.rb +140 -0
  100. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +50 -48
  101. data/spec/rubocop/cop/lint/useless_else_without_rescue_spec.rb +1 -1
  102. data/spec/rubocop/cop/lint/useless_setter_call_spec.rb +2 -0
  103. data/spec/rubocop/cop/rails/delegate_spec.rb +152 -0
  104. data/spec/rubocop/cop/style/encoding_spec.rb +131 -36
  105. data/spec/rubocop/cop/style/indentation_width_spec.rb +79 -0
  106. data/spec/rubocop/cop/style/redundant_begin_spec.rb +32 -0
  107. data/spec/rubocop/cop/style/regexp_literal_spec.rb +83 -13
  108. data/spec/rubocop/cop/style/string_literals_spec.rb +9 -3
  109. data/spec/rubocop/cop/style/trailing_blank_lines_spec.rb +65 -25
  110. data/spec/rubocop/cop/style/trivial_accessors_spec.rb +76 -0
  111. data/spec/rubocop/cop/style/unneeded_capital_w_spec.rb +85 -0
  112. data/spec/rubocop/cop/team_spec.rb +43 -0
  113. data/spec/rubocop/cop/{variable_inspector → variable_force}/assignment_spec.rb +3 -3
  114. data/spec/rubocop/cop/{variable_inspector → variable_force}/locatable_spec.rb +3 -3
  115. data/spec/rubocop/cop/{variable_inspector → variable_force}/scope_spec.rb +30 -2
  116. data/spec/rubocop/cop/{variable_inspector → variable_force}/variable_spec.rb +12 -27
  117. data/spec/rubocop/cop/{variable_inspector → variable_force}/variable_table_spec.rb +1 -1
  118. data/spec/rubocop/cop/{variable_inspector_spec.rb → variable_force_spec.rb} +4 -8
  119. data/spec/rubocop/formatter/base_formatter_spec.rb +2 -2
  120. data/spec/rubocop/formatter/offense_count_formatter_spec.rb +1 -1
  121. data/spec/rubocop/formatter/progress_formatter_spec.rb +1 -1
  122. data/spec/rubocop/options_spec.rb +2 -2
  123. data/spec/rubocop/path_util_spec.rb +47 -14
  124. data/spec/spec_helper.rb +9 -3
  125. data/spec/support/file_helper.rb +2 -0
  126. metadata +43 -26
  127. data/lib/rubocop/cop/style/final_newline.rb +0 -29
  128. data/spec/rubocop/cop/style/final_newline_spec.rb +0 -30
@@ -18,7 +18,7 @@ module Rubocop
18
18
  MSG = 'Never put a space between a method name and the opening ' \
19
19
  'parenthesis.'
20
20
 
21
- def check(_node, _method_name, args, body)
21
+ def check(_node, _method_name, args, _body)
22
22
  return unless args.loc.begin && args.loc.begin.is?('(')
23
23
  expr = args.loc.expression
24
24
  pos_before_left_paren = Parser::Source::Range.new(expr.source_buffer,
@@ -10,7 +10,7 @@ module Rubocop
10
10
 
11
11
  private
12
12
 
13
- def message(node)
13
+ def message(*)
14
14
  if style == :single_quotes
15
15
  "Prefer single-quoted strings when you don't need string " \
16
16
  'interpolation or special symbols.'
@@ -3,40 +3,54 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  module Style
6
- # This cop looks for trailing blank lines in the source code.
6
+ # This cop looks for trailing blank lines and a final newline in the
7
+ # source code.
7
8
  class TrailingBlankLines < Cop
8
- MSG = '%d trailing blank lines detected.'
9
+ include ConfigurableEnforcedStyle
9
10
 
10
11
  def investigate(processed_source)
11
- blank_lines = 0
12
+ sb = processed_source.buffer
13
+ return if sb.source.empty?
12
14
 
13
- processed_source.lines.reverse_each do |line|
14
- if line.blank?
15
- blank_lines += 1
16
- else
17
- break
18
- end
15
+ whitespace_at_end = sb.source[/\s*\Z/]
16
+ blank_lines = whitespace_at_end.count("\n") - 1
17
+ wanted_blank_lines = style == :final_newline ? 0 : 1
18
+
19
+ if blank_lines != wanted_blank_lines
20
+ begin_pos = sb.source.length - whitespace_at_end.length
21
+ autocorrect_range = Parser::Source::Range.new(sb, begin_pos,
22
+ sb.source.length)
23
+ begin_pos += "\n".length unless whitespace_at_end.length == 0
24
+ report_range = Parser::Source::Range.new(sb, begin_pos,
25
+ sb.source.length)
26
+ add_offense(autocorrect_range, report_range,
27
+ message(wanted_blank_lines, blank_lines))
19
28
  end
29
+ end
20
30
 
21
- if blank_lines > 0
22
- range_size =
23
- processed_source.raw_lines.to_a[-blank_lines..-1].join.length
24
- range = source_range(processed_source.buffer,
25
- processed_source[0...-blank_lines],
26
- 0, range_size)
27
- add_offense(range, range, format(MSG, blank_lines))
31
+ private
32
+
33
+ def message(wanted_blank_lines, blank_lines)
34
+ case blank_lines
35
+ when -1
36
+ 'Final newline missing.'
37
+ when 0
38
+ 'Trailing blank line missing.'
39
+ else
40
+ instead_of = if wanted_blank_lines == 0
41
+ ''
42
+ else
43
+ "instead of #{wanted_blank_lines} "
44
+ end
45
+ format('%d trailing blank lines %sdetected.', blank_lines,
46
+ instead_of)
28
47
  end
29
48
  end
30
49
 
31
50
  def autocorrect(range)
32
- # Bail out if there's also trailing whitespace, because
33
- # auto-correction in the two cops would result in clobbering.
34
- if range.source =~ / / &&
35
- config.for_cop('TrailingWhitespace')['Enabled']
36
- return
51
+ @corrections << lambda do |corrector|
52
+ corrector.replace(range, style == :final_newline ? "\n" : "\n\n")
37
53
  end
38
-
39
- @corrections << ->(corrector) { corrector.remove(range) }
40
54
  end
41
55
  end
42
56
  end
@@ -56,8 +56,7 @@ module Rubocop
56
56
  should_have_comma = style == :comma && multiline?(node)
57
57
  if comma_offset
58
58
  unless should_have_comma
59
- avoid_comma(items, kind,
60
- after_last_item.begin_pos + comma_offset, sb)
59
+ avoid_comma(kind, after_last_item.begin_pos + comma_offset, sb)
61
60
  end
62
61
  elsif should_have_comma
63
62
  put_comma(items, kind, sb)
@@ -79,7 +78,7 @@ module Rubocop
79
78
  [node.loc.begin, node.loc.end].map(&:line).uniq.size > 1
80
79
  end
81
80
 
82
- def avoid_comma(items, kind, comma_begin_pos, sb)
81
+ def avoid_comma(kind, comma_begin_pos, sb)
83
82
  range = Parser::Source::Range.new(sb, comma_begin_pos,
84
83
  comma_begin_pos + 1)
85
84
  article = kind =~ /array/ ? 'an' : 'a'
@@ -32,6 +32,10 @@ module Rubocop
32
32
  cop_config['AllowPredicates']
33
33
  end
34
34
 
35
+ def allow_dsl_writers?
36
+ cop_config['AllowDSLWriters']
37
+ end
38
+
35
39
  def whitelist
36
40
  whitelist = cop_config['Whitelist']
37
41
  Array(whitelist).map(&:to_sym) + [:initialize]
@@ -41,9 +45,14 @@ module Rubocop
41
45
  method_name[-1] == '?'
42
46
  end
43
47
 
48
+ def dsl_writer?(method_name)
49
+ !method_name.to_s.end_with?('=')
50
+ end
51
+
44
52
  def trivial_reader?(method_name, args, body)
45
53
  looks_like_trivial_reader?(args, body) &&
46
- !allowed_method?(method_name, body)
54
+ !allowed_method?(method_name, body) &&
55
+ !allowed_reader?(method_name)
47
56
  end
48
57
 
49
58
  def looks_like_trivial_reader?(args, body)
@@ -52,7 +61,8 @@ module Rubocop
52
61
 
53
62
  def trivial_writer?(method_name, args, body)
54
63
  looks_like_trivial_writer?(args, body) &&
55
- !allowed_method?(method_name, body)
64
+ !allowed_method?(method_name, body) &&
65
+ !allowed_writer?(method_name)
56
66
  end
57
67
 
58
68
  def looks_like_trivial_writer?(args, body)
@@ -62,16 +72,42 @@ module Rubocop
62
72
  end
63
73
 
64
74
  def allowed_method?(method_name, body)
65
- allow_predicates? && predicate?(method_name) ||
66
- whitelist.include?(method_name) ||
75
+ whitelist.include?(method_name) ||
67
76
  exact_name_match? && !names_match?(method_name, body)
68
77
  end
69
78
 
79
+ def allowed_writer?(method_name)
80
+ allow_dsl_writers? && dsl_writer?(method_name)
81
+ end
82
+
83
+ def allowed_reader?(method_name)
84
+ allow_predicates? && predicate?(method_name)
85
+ end
86
+
70
87
  def names_match?(method_name, body)
71
88
  ivar_name, = *body
72
89
 
73
90
  method_name.to_s.chomp('=') == ivar_name[1..-1]
74
91
  end
92
+
93
+ def autocorrect(node)
94
+ method_name, args, body = *node
95
+ return unless node.type == :def
96
+ return unless names_match?(method_name, body)
97
+ kind = if trivial_writer?(method_name, args, body)
98
+ return if dsl_writer?(method_name)
99
+ 'writer'
100
+ elsif trivial_reader?(method_name, args, body)
101
+ 'reader'
102
+ end
103
+
104
+ @corrections << lambda do |corrector|
105
+ corrector.replace(
106
+ node.loc.expression,
107
+ "attr_#{kind} :#{method_name.to_s.chomp('=')}"
108
+ )
109
+ end
110
+ end
75
111
  end
76
112
  end
77
113
  end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for usage of the %W() syntax when %w() would do.
7
+ class UnneededCapitalW < Cop
8
+ include PercentLiteral
9
+
10
+ MSG =
11
+ 'Do not use `%W` unless interpolation is needed. If not, use `%w`.'
12
+
13
+ def on_array(node)
14
+ process(node, '%W')
15
+ end
16
+
17
+ private
18
+
19
+ def on_percent_literal(node, types)
20
+ type = type(node)
21
+ if types.include?(type) &&
22
+ node.children.none? { |x| x.type == :dstr }
23
+ add_offense(node, :expression)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -32,7 +32,7 @@ module Rubocop
32
32
  return Lint::Syntax.offenses_from_diagnostics(diagnostics)
33
33
  end
34
34
 
35
- commissioner = Commissioner.new(cops)
35
+ commissioner = Commissioner.new(cops, forces)
36
36
  offenses = commissioner.investigate(processed_source)
37
37
  process_commissioner_errors(
38
38
  processed_source.file_path, commissioner.errors)
@@ -50,11 +50,19 @@ module Rubocop
50
50
  end
51
51
  end
52
52
 
53
+ def forces
54
+ @forces ||= Force.all.each_with_object([]) do |force_class, forces|
55
+ joining_cops = cops.select { |cop| cop.join_force?(force_class) }
56
+ next if joining_cops.empty?
57
+ forces << force_class.new(joining_cops)
58
+ end
59
+ end
60
+
53
61
  private
54
62
 
55
63
  def cop_enabled?(cop_class)
56
64
  @config.cop_enabled?(cop_class) ||
57
- cop_class.cop_name == @options[:only]
65
+ (@options[:only] || []).include?(cop_class.cop_name)
58
66
  end
59
67
 
60
68
  def autocorrect(buffer, cops)
@@ -144,8 +144,8 @@ module Rubocop
144
144
  Parser::Source::Range.new(@processed_source.buffer, begin_pos, end_pos)
145
145
  end
146
146
 
147
- # Returns for example a bare `if` node if the given node is an `if` whith
148
- # calls chained to the end of it.
147
+ # Returns, for example, a bare `if` node if the given node is an `if`
148
+ # with calls chained to the end of it.
149
149
  def first_part_of_call_chain(node)
150
150
  while node
151
151
  case node.type
@@ -2,23 +2,37 @@
2
2
 
3
3
  module Rubocop
4
4
  module Cop
5
- # This module provides a way to track local variables and scopes of Ruby.
6
- # This is intended to be used as mix-in, and the user class may override
7
- # some of the hook methods.
8
- module VariableInspector
5
+ # This force provides a way to track local variables and scopes of Ruby.
6
+ # Cops intertact with this force need to override some of the hook methods.
7
+ #
8
+ # def before_entering_scope(scope, variable_table)
9
+ # end
10
+ #
11
+ # def after_entering_scope(scope, variable_table)
12
+ # end
13
+ #
14
+ # def before_leaving_scope(scope, variable_table)
15
+ # end
16
+ #
17
+ # def after_leaving_scope(scope, variable_table)
18
+ # end
19
+ #
20
+ # def before_declaring_variable(variable, variable_table)
21
+ # end
22
+ #
23
+ # def after_declaring_variable(variable, variable_table)
24
+ # end
25
+ class VariableForce < Force # rubocop:disable ClassLength
9
26
  VARIABLE_ASSIGNMENT_TYPE = :lvasgn
10
27
  REGEXP_NAMED_CAPTURE_TYPE = :match_with_lvasgn
11
28
  VARIABLE_ASSIGNMENT_TYPES =
12
29
  [VARIABLE_ASSIGNMENT_TYPE, REGEXP_NAMED_CAPTURE_TYPE].freeze
13
30
 
14
- METHOD_ARGUMENT_DECLARATION_TYPES = [
31
+ ARGUMENT_DECLARATION_TYPES = [
15
32
  :arg, :optarg, :restarg,
16
- :kwarg, :kwoptarg, :kwrestarg
33
+ :kwarg, :kwoptarg, :kwrestarg,
34
+ :blockarg # This doen't mean block argument, it's block-pass (&block).
17
35
  ].freeze
18
- BLOCK_ARGUMENT_DECLARATION_TYPE = :blockarg
19
- ARGUMENT_DECLARATION_TYPES = (
20
- METHOD_ARGUMENT_DECLARATION_TYPES + [BLOCK_ARGUMENT_DECLARATION_TYPE]
21
- ).freeze
22
36
  BLOCK_LOCAL_VARIABLE_DECLARATION_TYPE = :shadowarg
23
37
  DECLARATION_TYPES = (
24
38
  ARGUMENT_DECLARATION_TYPES + [BLOCK_LOCAL_VARIABLE_DECLARATION_TYPE]
@@ -42,27 +56,26 @@ module Rubocop
42
56
  TWISTED_SCOPE_TYPES = [:block, :class, :sclass, :defs].freeze
43
57
  SCOPE_TYPES = (TWISTED_SCOPE_TYPES + [:top_level, :module, :def]).freeze
44
58
 
59
+ def self.wrap_with_top_level_node(node)
60
+ # This is a custom node type, not defined in Parser.
61
+ Parser::AST::Node.new(:top_level, [node])
62
+ end
63
+
45
64
  def variable_table
46
65
  @variable_table ||= VariableTable.new(self)
47
66
  end
48
67
 
49
68
  # Starting point.
50
- def inspect_variables(root_node)
69
+ def investigate(processed_source)
70
+ root_node = processed_source.ast
51
71
  return unless root_node
52
72
 
53
73
  # Wrap the root node with :top_level scope node.
54
- top_level_node = wrap_with_top_level_node(root_node)
74
+ top_level_node = self.class.wrap_with_top_level_node(root_node)
55
75
 
56
76
  inspect_variables_in_scope(top_level_node)
57
77
  end
58
78
 
59
- def wrap_with_top_level_node(node)
60
- # This is a custom node type, not defined in Parser.
61
- Parser::AST::Node.new(:top_level, [node])
62
- end
63
-
64
- module_function :wrap_with_top_level_node
65
-
66
79
  # This is called for each scope recursively.
67
80
  def inspect_variables_in_scope(scope_node)
68
81
  variable_table.push_scope(scope_node)
@@ -339,24 +352,19 @@ module Rubocop
339
352
  @scanned_nodes ||= []
340
353
  end
341
354
 
342
- # Hooks
343
-
344
- def before_entering_scope(scope)
345
- end
346
-
347
- def after_entering_scope(scope)
348
- end
349
-
350
- def before_leaving_scope(scope)
351
- end
352
-
353
- def after_leaving_scope(scope)
354
- end
355
-
356
- def before_declaring_variable(variable_variable)
357
- end
358
-
359
- def after_declaring_variable(variable_variable)
355
+ # Hooks invoked by VariableTable.
356
+ [
357
+ :before_entering_scope,
358
+ :after_entering_scope,
359
+ :before_leaving_scope,
360
+ :after_leaving_scope,
361
+ :before_declaring_variable,
362
+ :after_declaring_variable
363
+ ].each do |hook|
364
+ define_method(hook) do |arg|
365
+ # Invoke hook in cops.
366
+ run_hook(hook, arg, variable_table)
367
+ end
360
368
  end
361
369
 
362
370
  # Post condition loops
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Rubocop
4
4
  module Cop
5
- module VariableInspector
5
+ class VariableForce
6
6
  # This class represents each assignment of a variable.
7
7
  class Assignment
8
8
  include Locatable
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Rubocop
4
4
  module Cop
5
- module VariableInspector
5
+ class VariableForce
6
6
  # This module provides a way to locate the conditional branch the node is
7
7
  # in. This is intended to be used as mix-in.
8
8
  module Locatable
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Rubocop
4
4
  module Cop
5
- module VariableInspector
5
+ class VariableForce
6
6
  # This class represents each reference of a variable.
7
7
  class Reference
8
8
  include Locatable
@@ -25,6 +25,18 @@ module Rubocop
25
25
  @node = node
26
26
  @scope = scope
27
27
  end
28
+
29
+ # There's an implicit variable reference by the zero-arity `super`:
30
+ #
31
+ # def some_method(foo)
32
+ # super
33
+ # end
34
+ #
35
+ # In this case, the variable `foo` is not explicitly referenced,
36
+ # but it can be considered used implicitly by the `super`.
37
+ def explicit?
38
+ @node.type != ZERO_ARITY_SUPER_TYPE
39
+ end
28
40
  end
29
41
  end
30
42
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Rubocop
4
4
  module Cop
5
- module VariableInspector
5
+ class VariableForce
6
6
  # A Scope represents a context of local variable visibility.
7
7
  # This is a place where local variables belong to.
8
8
  # A scope instance holds a scope node and variable entries.
@@ -24,6 +24,14 @@ module Rubocop
24
24
  @node.equal?(other.node)
25
25
  end
26
26
 
27
+ def name
28
+ case @node.type
29
+ when :def then @node.children[0]
30
+ when :defs then @node.children[1]
31
+ else nil # TODO
32
+ end
33
+ end
34
+
27
35
  def body_node
28
36
  child_index = case @node.type
29
37
  when :top_level then 0