rubocop 0.31.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +315 -0
  3. data/README.md +199 -38
  4. data/config/default.yml +91 -12
  5. data/config/disabled.yml +45 -4
  6. data/config/enabled.yml +107 -9
  7. data/lib/rubocop/ast_node.rb +48 -0
  8. data/lib/rubocop/cli.rb +11 -1
  9. data/lib/rubocop/comment_config.rb +4 -1
  10. data/lib/rubocop/config.rb +26 -17
  11. data/lib/rubocop/config_loader.rb +61 -14
  12. data/lib/rubocop/cop/commissioner.rb +7 -12
  13. data/lib/rubocop/cop/cop.rb +43 -20
  14. data/lib/rubocop/cop/lint/block_alignment.rb +1 -1
  15. data/lib/rubocop/cop/lint/circular_argument_reference.rb +69 -0
  16. data/lib/rubocop/cop/lint/debugger.rb +9 -48
  17. data/lib/rubocop/cop/lint/def_end_alignment.rb +8 -4
  18. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +42 -23
  19. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
  20. data/lib/rubocop/cop/lint/duplicated_key.rb +37 -0
  21. data/lib/rubocop/cop/lint/end_alignment.rb +33 -13
  22. data/lib/rubocop/cop/lint/eval.rb +6 -2
  23. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +175 -0
  24. data/lib/rubocop/cop/lint/literal_in_condition.rb +0 -5
  25. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +10 -0
  26. data/lib/rubocop/cop/lint/nested_method_definition.rb +31 -0
  27. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +19 -1
  28. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  29. data/lib/rubocop/cop/lint/space_before_first_arg.rb +1 -1
  30. data/lib/rubocop/cop/lint/unneeded_disable.rb +72 -0
  31. data/lib/rubocop/cop/lint/unused_block_argument.rb +6 -0
  32. data/lib/rubocop/cop/lint/unused_method_argument.rb +8 -0
  33. data/lib/rubocop/cop/metrics/abc_size.rb +17 -6
  34. data/lib/rubocop/cop/metrics/class_length.rb +1 -1
  35. data/lib/rubocop/cop/metrics/method_length.rb +1 -3
  36. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  37. data/lib/rubocop/cop/metrics/parameter_lists.rb +1 -1
  38. data/lib/rubocop/cop/mixin/access_modifier_node.rb +1 -1
  39. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -2
  40. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +28 -4
  41. data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +26 -3
  42. data/lib/rubocop/cop/mixin/check_assignment.rb +2 -3
  43. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +59 -12
  44. data/lib/rubocop/cop/mixin/configurable_max.rb +1 -1
  45. data/lib/rubocop/cop/mixin/configurable_naming.rb +14 -3
  46. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -3
  47. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +10 -1
  48. data/lib/rubocop/cop/mixin/first_element_line_break.rb +41 -0
  49. data/lib/rubocop/cop/mixin/if_node.rb +10 -0
  50. data/lib/rubocop/cop/mixin/method_preference.rb +28 -0
  51. data/lib/rubocop/cop/mixin/negative_conditional.rb +1 -1
  52. data/lib/rubocop/cop/mixin/on_method_def.rb +4 -5
  53. data/lib/rubocop/cop/mixin/safe_assignment.rb +3 -14
  54. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +8 -1
  55. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +8 -1
  56. data/lib/rubocop/cop/mixin/statement_modifier.rb +4 -7
  57. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  58. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  59. data/lib/rubocop/cop/mixin/surrounding_space.rb +5 -4
  60. data/lib/rubocop/cop/offense.rb +16 -3
  61. data/lib/rubocop/cop/performance/case_when_splat.rb +160 -0
  62. data/lib/rubocop/cop/performance/count.rb +35 -30
  63. data/lib/rubocop/cop/performance/detect.rb +16 -3
  64. data/lib/rubocop/cop/performance/fixed_size.rb +50 -0
  65. data/lib/rubocop/cop/performance/flat_map.rb +3 -3
  66. data/lib/rubocop/cop/performance/sample.rb +103 -59
  67. data/lib/rubocop/cop/performance/size.rb +2 -1
  68. data/lib/rubocop/cop/performance/string_replacement.rb +187 -0
  69. data/lib/rubocop/cop/rails/action_filter.rb +31 -5
  70. data/lib/rubocop/cop/rails/date.rb +15 -14
  71. data/lib/rubocop/cop/rails/pluralization_grammar.rb +97 -0
  72. data/lib/rubocop/cop/rails/read_write_attribute.rb +1 -1
  73. data/lib/rubocop/cop/rails/time_zone.rb +46 -18
  74. data/lib/rubocop/cop/style/alias.rb +1 -0
  75. data/lib/rubocop/cop/style/align_hash.rb +8 -15
  76. data/lib/rubocop/cop/style/align_parameters.rb +19 -7
  77. data/lib/rubocop/cop/style/and_or.rb +42 -13
  78. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +2 -1
  79. data/lib/rubocop/cop/style/block_comments.rb +4 -2
  80. data/lib/rubocop/cop/style/block_delimiters.rb +69 -24
  81. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +40 -12
  82. data/lib/rubocop/cop/style/case_indentation.rb +18 -4
  83. data/lib/rubocop/cop/style/collection_methods.rb +2 -20
  84. data/lib/rubocop/cop/style/command_literal.rb +2 -10
  85. data/lib/rubocop/cop/style/comment_annotation.rb +29 -8
  86. data/lib/rubocop/cop/style/copyright.rb +5 -3
  87. data/lib/rubocop/cop/style/documentation.rb +21 -12
  88. data/lib/rubocop/cop/style/dot_position.rb +6 -0
  89. data/lib/rubocop/cop/style/double_negation.rb +4 -15
  90. data/lib/rubocop/cop/style/each_with_object.rb +17 -4
  91. data/lib/rubocop/cop/style/else_alignment.rb +2 -1
  92. data/lib/rubocop/cop/style/empty_else.rb +25 -0
  93. data/lib/rubocop/cop/style/empty_line_between_defs.rb +39 -14
  94. data/lib/rubocop/cop/style/encoding.rb +10 -4
  95. data/lib/rubocop/cop/style/extra_spacing.rb +126 -5
  96. data/lib/rubocop/cop/style/first_array_element_line_break.rb +41 -0
  97. data/lib/rubocop/cop/style/first_hash_element_line_break.rb +35 -0
  98. data/lib/rubocop/cop/style/first_method_argument_line_break.rb +37 -0
  99. data/lib/rubocop/cop/style/first_method_parameter_line_break.rb +42 -0
  100. data/lib/rubocop/cop/style/first_parameter_indentation.rb +5 -3
  101. data/lib/rubocop/cop/style/for.rb +2 -1
  102. data/lib/rubocop/cop/style/hash_syntax.rb +5 -0
  103. data/lib/rubocop/cop/style/if_unless_modifier.rb +32 -5
  104. data/lib/rubocop/cop/style/indent_hash.rb +67 -37
  105. data/lib/rubocop/cop/style/indentation_width.rb +36 -10
  106. data/lib/rubocop/cop/style/initial_indentation.rb +37 -0
  107. data/lib/rubocop/cop/style/leading_comment_space.rb +3 -2
  108. data/lib/rubocop/cop/style/method_call_parentheses.rb +28 -1
  109. data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -7
  110. data/lib/rubocop/cop/style/multiline_operation_indentation.rb +21 -24
  111. data/lib/rubocop/cop/style/mutable_constant.rb +35 -0
  112. data/lib/rubocop/cop/style/nested_modifier.rb +97 -0
  113. data/lib/rubocop/cop/style/next.rb +50 -15
  114. data/lib/rubocop/cop/style/non_nil_check.rb +12 -8
  115. data/lib/rubocop/cop/style/one_line_conditional.rb +8 -4
  116. data/lib/rubocop/cop/style/option_hash.rb +64 -0
  117. data/lib/rubocop/cop/style/optional_arguments.rb +49 -0
  118. data/lib/rubocop/cop/style/parallel_assignment.rb +218 -0
  119. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +3 -66
  120. data/lib/rubocop/cop/style/predicate_name.rb +7 -2
  121. data/lib/rubocop/cop/style/redundant_begin.rb +2 -13
  122. data/lib/rubocop/cop/style/redundant_freeze.rb +37 -0
  123. data/lib/rubocop/cop/style/redundant_return.rb +32 -3
  124. data/lib/rubocop/cop/style/regexp_literal.rb +2 -10
  125. data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +81 -0
  126. data/lib/rubocop/cop/style/rescue_modifier.rb +30 -22
  127. data/lib/rubocop/cop/style/send.rb +18 -0
  128. data/lib/rubocop/cop/style/signal_exception.rb +24 -11
  129. data/lib/rubocop/cop/style/single_line_methods.rb +8 -9
  130. data/lib/rubocop/cop/style/single_space_before_first_arg.rb +1 -1
  131. data/lib/rubocop/cop/style/space_around_operators.rb +2 -0
  132. data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +61 -0
  133. data/lib/rubocop/cop/style/special_global_vars.rb +4 -2
  134. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +108 -0
  135. data/lib/rubocop/cop/style/string_methods.rb +32 -0
  136. data/lib/rubocop/cop/style/struct_inheritance.rb +11 -10
  137. data/lib/rubocop/cop/style/symbol_literal.rb +1 -1
  138. data/lib/rubocop/cop/style/symbol_proc.rb +62 -13
  139. data/lib/rubocop/cop/style/trailing_blank_lines.rb +9 -1
  140. data/lib/rubocop/cop/style/trailing_comma.rb +17 -7
  141. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -2
  142. data/lib/rubocop/cop/style/trivial_accessors.rb +10 -1
  143. data/lib/rubocop/cop/style/unneeded_percent_q.rb +31 -20
  144. data/lib/rubocop/cop/style/variable_name.rb +5 -0
  145. data/lib/rubocop/cop/style/while_until_do.rb +1 -1
  146. data/lib/rubocop/cop/style/word_array.rb +15 -2
  147. data/lib/rubocop/cop/team.rb +25 -5
  148. data/lib/rubocop/cop/util.rb +7 -2
  149. data/lib/rubocop/cop/variable_force/locatable.rb +6 -6
  150. data/lib/rubocop/cop/variable_force.rb +10 -10
  151. data/lib/rubocop/formatter/base_formatter.rb +1 -1
  152. data/lib/rubocop/formatter/disabled_config_formatter.rb +70 -8
  153. data/lib/rubocop/formatter/formatter_set.rb +27 -1
  154. data/lib/rubocop/formatter/progress_formatter.rb +10 -2
  155. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  156. data/lib/rubocop/node_pattern.rb +390 -0
  157. data/lib/rubocop/options.rb +148 -81
  158. data/lib/rubocop/processed_source.rb +7 -2
  159. data/lib/rubocop/rake_task.rb +1 -1
  160. data/lib/rubocop/remote_config.rb +60 -0
  161. data/lib/rubocop/result_cache.rb +123 -0
  162. data/lib/rubocop/runner.rb +85 -22
  163. data/lib/rubocop/target_finder.rb +4 -4
  164. data/lib/rubocop/token.rb +2 -1
  165. data/lib/rubocop/version.rb +1 -1
  166. data/lib/rubocop/warning.rb +11 -0
  167. data/lib/rubocop.rb +32 -3
  168. data/relnotes/v0.32.0.md +139 -0
  169. data/relnotes/v0.32.1.md +122 -0
  170. data/relnotes/v0.33.0.md +157 -0
  171. data/relnotes/v0.34.0.md +182 -0
  172. data/relnotes/v0.34.1.md +129 -0
  173. data/relnotes/v0.34.2.md +139 -0
  174. data/relnotes/v0.35.0.md +210 -0
  175. data/rubocop.gemspec +4 -4
  176. metadata +50 -12
  177. data/lib/rubocop/cop/performance/parallel_assignment.rb +0 -79
@@ -12,12 +12,12 @@ module RuboCop
12
12
  # The cop also reports warnings when you are using 'to_time' method,
13
13
  # because it doesn't know about Rails time zone too.
14
14
  #
15
- # Two styles are supported for this cop. When EnforcedStyle is 'always'
15
+ # Two styles are supported for this cop. When EnforcedStyle is 'strict'
16
16
  # then the Date methods (today, current, yesterday, tomorrow)
17
17
  # are prohibited and the usage of both 'to_time'
18
18
  # and 'to_time_in_current_zone' is reported as warning.
19
19
  #
20
- # When EnforcedStyle is 'acceptable' then only 'Date.today' is prohibited
20
+ # When EnforcedStyle is 'flexible' then only 'Date.today' is prohibited
21
21
  # and only 'to_time' is reported as warning.
22
22
  #
23
23
  # @example
@@ -33,29 +33,30 @@ module RuboCop
33
33
  # Date.today
34
34
  # date.to_time
35
35
  #
36
- # # reports offense only when style is 'always'
36
+ # # reports offense only when style is 'strict'
37
37
  # date.to_time_in_current_zone
38
38
  class Date < Cop
39
39
  include ConfigurableEnforcedStyle
40
40
 
41
41
  MSG = 'Do not use `%s` without zone. Use `%s` instead.'
42
42
 
43
- MSG_SEND = 'Do not use `%s` on Date objects,' \
44
- 'because it knows nothing about time zone in use.'
43
+ MSG_SEND = 'Do not use `%s` on Date objects, ' \
44
+ 'because they know nothing about the time zone in use.'
45
45
 
46
46
  BAD_DAYS = [:today, :current, :yesterday, :tomorrow]
47
47
 
48
48
  def on_const(node)
49
- _, klass = *node.children
50
-
51
- return unless method_send?(node)
49
+ mod, klass = *node.children
50
+ # we should only check core Date class (`Date` or `::Date`)
51
+ return unless (mod.nil? || mod.cbase_type?) && method_send?(node)
52
52
 
53
53
  check_date_node(node.parent) if klass == :Date
54
54
  end
55
55
 
56
56
  def on_send(node)
57
- method_name = extract_method(node)
58
- return unless bad_methods.include?(method_name)
57
+ receiver, method_name, *args = *node
58
+ return unless receiver && bad_methods.include?(method_name)
59
+ return if method_name == :to_time && args.length == 1
59
60
 
60
61
  add_offense(node, :selector,
61
62
  format(MSG_SEND,
@@ -75,7 +76,7 @@ module RuboCop
75
76
  add_offense(node, :selector,
76
77
  format(MSG,
77
78
  "Date.#{method_name}",
78
- 'Time.zone.today')
79
+ "Time.zone.#{method_name}")
79
80
  )
80
81
  end
81
82
 
@@ -96,7 +97,7 @@ module RuboCop
96
97
  # checks that parent node of send_type
97
98
  # and receiver is the given node
98
99
  def method_send?(node)
99
- return false unless node.parent.send_type?
100
+ return false unless node.parent && node.parent.send_type?
100
101
 
101
102
  receiver, _method_name, *_args = *node.parent
102
103
 
@@ -104,7 +105,7 @@ module RuboCop
104
105
  end
105
106
 
106
107
  def good_days
107
- style == :always ? [] : [:current, :yesterday, :tomorrow]
108
+ style == :strict ? [] : [:current, :yesterday, :tomorrow]
108
109
  end
109
110
 
110
111
  def bad_days
@@ -112,7 +113,7 @@ module RuboCop
112
113
  end
113
114
 
114
115
  def bad_methods
115
- style == :always ? [:to_time, :to_time_in_current_zone] : [:to_time]
116
+ style == :strict ? [:to_time, :to_time_in_current_zone] : [:to_time]
116
117
  end
117
118
  end
118
119
  end
@@ -0,0 +1,97 @@
1
+ # encoding: utf-8
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks for correct grammar when using ActiveSupport's
7
+ # core extensions to the numeric classes.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # 3.day.ago
12
+ # 1.months.ago
13
+ #
14
+ # # good
15
+ # 3.days.ago
16
+ # 1.month.ago
17
+ class PluralizationGrammar < Cop
18
+ SINGULAR_DURATION_METHODS = { second: :seconds,
19
+ minute: :minutes,
20
+ hour: :hours,
21
+ day: :days,
22
+ week: :weeks,
23
+ fortnight: :fortnights,
24
+ month: :months,
25
+ year: :years }
26
+
27
+ PLURAL_DURATION_METHODS = SINGULAR_DURATION_METHODS.invert
28
+
29
+ MSG = 'Prefer `%s.%s`.'
30
+
31
+ def on_send(node)
32
+ receiver, method_name, *_args = *node
33
+ return if receiver.nil?
34
+ return unless duration_method?(method_name)
35
+ return unless literal_number?(receiver)
36
+ number, = *receiver
37
+ if singular_receiver?(number) && plural_method?(method_name)
38
+ add_offense(node,
39
+ :expression,
40
+ format(MSG, number, singularize(method_name)))
41
+ elsif plural_receiver?(number) && singular_method?(method_name)
42
+ add_offense(node,
43
+ :expression,
44
+ format(MSG, number, pluralize(method_name)))
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def autocorrect(node)
51
+ lambda do |corrector|
52
+ method_name = node.loc.selector.source
53
+ replacement = if plural_method?(method_name)
54
+ singularize(method_name)
55
+ else
56
+ pluralize(method_name)
57
+ end
58
+ corrector.replace(node.loc.selector, replacement)
59
+ end
60
+ end
61
+
62
+ def plural_method?(method_name)
63
+ method_name.to_s.end_with?('s')
64
+ end
65
+
66
+ def singular_method?(method_name)
67
+ !plural_method?(method_name)
68
+ end
69
+
70
+ def singular_receiver?(number)
71
+ number == 1
72
+ end
73
+
74
+ def plural_receiver?(number)
75
+ !singular_receiver?(number)
76
+ end
77
+
78
+ def literal_number?(node)
79
+ node.int_type? || node.float_type?
80
+ end
81
+
82
+ def pluralize(method_name)
83
+ SINGULAR_DURATION_METHODS.fetch(method_name.to_sym).to_s
84
+ end
85
+
86
+ def singularize(method_name)
87
+ PLURAL_DURATION_METHODS.fetch(method_name.to_sym).to_s
88
+ end
89
+
90
+ def duration_method?(method_name)
91
+ SINGULAR_DURATION_METHODS.key?(method_name) ||
92
+ PLURAL_DURATION_METHODS.key?(method_name)
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -33,7 +33,7 @@ module RuboCop
33
33
  if method_name == :read_attribute
34
34
  format(MSG, 'self[:attr]', 'read_attribute(:attr)')
35
35
  else
36
- format(MSG, 'self[:attr] = val', 'write_attribute(:attr, var)')
36
+ format(MSG, 'self[:attr] = val', 'write_attribute(:attr, val)')
37
37
  end
38
38
  end
39
39
 
@@ -8,10 +8,10 @@ module RuboCop
8
8
  # Built on top of Ruby on Rails style guide (https://github.com/bbatsov/rails-style-guide#time)
9
9
  # and the article http://danilenko.org/2012/7/6/rails_timezones/ .
10
10
  #
11
- # Two styles are supported for this cop. When EnforcedStyle is 'always'
11
+ # Two styles are supported for this cop. When EnforcedStyle is 'strict'
12
12
  # then only use of Time.zone is allowed.
13
13
  #
14
- # When EnforcedStyle is 'acceptable' then it's also allowed
14
+ # When EnforcedStyle is 'flexible' then it's also allowed
15
15
  # to use Time.in_time_zone.
16
16
  #
17
17
  # @example
@@ -24,6 +24,7 @@ module RuboCop
24
24
  # Time.zone.parse('2015-03-02 19:05:37')
25
25
  #
26
26
  # # no offense only if style is 'acceptable'
27
+ # Time.current
27
28
  # DateTime.strptime(str, "%Y-%m-%d %H:%M %Z").in_time_zone
28
29
  # Time.at(timestamp).in_time_zone
29
30
  class TimeZone < Cop
@@ -35,18 +36,22 @@ module RuboCop
35
36
 
36
37
  MSG_LOCALTIME = 'Do not use `Time.localtime` without offset or zone.'
37
38
 
39
+ MSG_CURRENT = 'Do not use `%s`. Use `Time.zone.now` instead.'
40
+
38
41
  TIMECLASS = [:Time, :DateTime]
39
42
 
40
- DANGER_METHODS = [:now, :local, :new, :strftime, :parse, :at]
43
+ DANGEROUS_METHODS = [:now, :local, :new, :strftime,
44
+ :parse, :at, :current]
41
45
 
42
- ACCEPTED_METHODS = [:in_time_zone, :utc,
46
+ ACCEPTED_METHODS = [:current, :in_time_zone, :utc, :getlocal,
43
47
  :iso8601, :jisx0301, :rfc3339,
44
48
  :to_i, :to_f]
45
49
 
46
50
  def on_const(node)
47
- _module, klass = *node
48
-
49
- return unless method_send?(node)
51
+ mod, klass = *node
52
+ # we should only check core class
53
+ # (`DateTime`/`Time` or `::Date`/`::DateTime`)
54
+ return unless (mod.nil? || mod.cbase_type?) && method_send?(node)
50
55
 
51
56
  check_time_node(klass, node.parent) if TIMECLASS.include?(klass)
52
57
  end
@@ -59,7 +64,9 @@ module RuboCop
59
64
 
60
65
  return check_localtime(node) if need_check_localtime?(chain)
61
66
 
62
- method_name = (chain & DANGER_METHODS).join('.')
67
+ method_name = (chain & DANGEROUS_METHODS).join('.')
68
+
69
+ return if offset_provided?(node)
63
70
 
64
71
  message = build_message(klass, method_name, node)
65
72
 
@@ -68,19 +75,19 @@ module RuboCop
68
75
 
69
76
  def build_message(klass, method_name, node)
70
77
  if acceptable?
71
- accepted_methods = ACCEPTED_METHODS.map do |am|
72
- "`#{klass}.#{method_name}.#{am}`"
73
- end
74
-
75
78
  format(MSG_ACCEPTABLE,
76
79
  "#{klass}.#{method_name}",
77
- accepted_methods.join(', ')
80
+ acceptable_methods(klass, method_name, node).join(', ')
81
+ )
82
+ elsif method_name == 'current'
83
+ format(MSG_CURRENT,
84
+ "#{klass}.#{method_name}"
78
85
  )
79
86
  else
80
87
  safe_method_name = safe_method(method_name, node)
81
88
  format(MSG,
82
89
  "#{klass}.#{method_name}",
83
- "#{klass}.zone.#{safe_method_name}"
90
+ "Time.zone.#{safe_method_name}"
84
91
  )
85
92
  end
86
93
  end
@@ -102,7 +109,7 @@ module RuboCop
102
109
  # checks that parent node of send_type
103
110
  # and receiver is the given node
104
111
  def method_send?(node)
105
- return false unless node.parent.send_type?
112
+ return false unless node.parent && node.parent.send_type?
106
113
 
107
114
  receiver, _method_name, *_args = *node.parent
108
115
 
@@ -132,7 +139,7 @@ module RuboCop
132
139
  end
133
140
 
134
141
  def danger_chain?(chain)
135
- (chain & DANGER_METHODS).empty? || !(chain & good_methods).empty?
142
+ (chain & DANGEROUS_METHODS).empty? || !(chain & good_methods).empty?
136
143
  end
137
144
 
138
145
  def need_check_localtime?(chain)
@@ -140,11 +147,32 @@ module RuboCop
140
147
  end
141
148
 
142
149
  def acceptable?
143
- style == :acceptable
150
+ style == :flexible
144
151
  end
145
152
 
146
153
  def good_methods
147
- style == :always ? [:zone] : [:zone] + ACCEPTED_METHODS
154
+ style == :strict ? [:zone] : [:zone] + ACCEPTED_METHODS
155
+ end
156
+
157
+ def acceptable_methods(klass, method_name, node)
158
+ acceptable = [
159
+ "`Time.zone.#{safe_method(method_name, node)}`"
160
+ ]
161
+
162
+ ACCEPTED_METHODS.each do |am|
163
+ acceptable << "`#{klass}.#{method_name}.#{am}`"
164
+ end
165
+
166
+ acceptable
167
+ end
168
+
169
+ # Time.new can be called with a time zone offset
170
+ # When it is, that should be considered safe
171
+ # Example:
172
+ # Time.new(1988, 3, 15, 3, 0, 0, "-05:00")
173
+ def offset_provided?(node)
174
+ _, _, *args = *node
175
+ args.length >= 7
148
176
  end
149
177
  end
150
178
  end
@@ -15,6 +15,7 @@ module RuboCop
15
15
  # using alias is the only option in certain scenarios
16
16
  # in such scenarios we don't want to report an offense
17
17
  return unless method_name == :instance_exec
18
+ return unless body
18
19
 
19
20
  body.each_node(:alias) { |n| ignore_node(n) }
20
21
  end
@@ -156,7 +156,7 @@ module RuboCop
156
156
  def on_hash(node)
157
157
  return if ignored_node?(node)
158
158
  return if node.children.empty?
159
- return unless multiline?(node)
159
+ return unless node.multiline?
160
160
 
161
161
  @alignment_for_hash_rockets ||=
162
162
  new_alignment('EnforcedHashRocketStyle')
@@ -201,17 +201,6 @@ module RuboCop
201
201
  node.loc.begin
202
202
  end
203
203
 
204
- # Returns true if the hash spans multiple lines
205
- def multiline?(node)
206
- return false unless node.loc.expression.source.include?("\n")
207
-
208
- return false if node.children[1..-1].all? do |child|
209
- !begins_its_line?(child.loc.expression)
210
- end
211
-
212
- true
213
- end
214
-
215
204
  def alignment_for(pair)
216
205
  if pair.loc.operator.is?('=>')
217
206
  @alignment_for_hash_rockets
@@ -231,9 +220,13 @@ module RuboCop
231
220
  key, value = *node
232
221
 
233
222
  lambda do |corrector|
234
- adjust(corrector, key_delta, key.loc.expression)
235
- adjust(corrector, separator_delta, node.loc.operator)
236
- adjust(corrector, value_delta, value.loc.expression)
223
+ if value.nil?
224
+ adjust(corrector, key_delta, node.loc.expression)
225
+ else
226
+ adjust(corrector, key_delta, key.loc.expression)
227
+ adjust(corrector, separator_delta, node.loc.operator)
228
+ adjust(corrector, value_delta, value.loc.expression)
229
+ end
237
230
  end
238
231
  end
239
232
 
@@ -3,23 +3,33 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Here we check if the parameters on a multi-line method call are
7
- # aligned.
6
+ # Here we check if the parameters on a multi-line method call or
7
+ # definition are aligned.
8
8
  class AlignParameters < Cop
9
9
  include AutocorrectAlignment
10
-
11
- MSG = 'Align the parameters of a method call if they span ' \
12
- 'more than one line.'
10
+ include OnMethodDef
13
11
 
14
12
  def on_send(node)
15
13
  _receiver, method, *args = *node
16
14
 
17
15
  return if method == :[]=
18
- return if args.size <= 1
16
+ return if args.size < 2
17
+
18
+ check_alignment(args, base_column(node, args))
19
+ end
19
20
 
21
+ def on_method_def(node, _method_name, args, _body)
22
+ args = args.children
23
+ return if args.size < 2
20
24
  check_alignment(args, base_column(node, args))
21
25
  end
22
26
 
27
+ def message(node)
28
+ type = node.parent.send_type? ? 'call' : 'definition'
29
+ "Align the parameters of a method #{type} if they span " \
30
+ 'more than one line.'
31
+ end
32
+
23
33
  private
24
34
 
25
35
  def fixed_indentation?
@@ -38,7 +48,9 @@ module RuboCop
38
48
  end
39
49
 
40
50
  def target_method_lineno(node)
41
- if node.loc.selector
51
+ if node.def_type? || node.defs_type?
52
+ node.loc.keyword.line
53
+ elsif node.loc.selector
42
54
  node.loc.selector.line
43
55
  else
44
56
  # l.(1) has no selector, so we use the opening parenthesis instead
@@ -63,25 +63,54 @@ module RuboCop
63
63
  replacement = (node.type == :and ? '&&' : '||')
64
64
  lambda do |corrector|
65
65
  [expr1, expr2].each do |expr|
66
- _receiver, _method_name, *args = *expr
67
- next unless correctable?(expr)
68
-
69
- sb = expr.loc.expression.source_buffer
70
- begin_paren = expr.loc.selector.end_pos
71
- end_paren = begin_paren + 1
72
- range = Parser::Source::Range.new(sb, begin_paren, end_paren)
73
- corrector.replace(range, '(')
74
- corrector.insert_after(args.last.loc.expression, ')')
66
+ if expr.send_type?
67
+ correct_send(expr, corrector)
68
+ elsif expr.return_type?
69
+ correct_other(expr, corrector)
70
+ elsif expr.assignment?
71
+ correct_other(expr, corrector)
72
+ end
75
73
  end
76
74
  corrector.replace(node.loc.operator, replacement)
77
75
  end
78
76
  end
79
77
 
80
- def correctable?(expr)
81
- return false unless expr.type == :send
82
- _receiver, method_name, *args = *expr
78
+ def correct_send(node, corrector)
79
+ receiver, method_name, *args = *node
80
+ if method_name == :!
81
+ # ! is a special case:
82
+ # 'x and !obj.method arg' can be auto-corrected if we
83
+ # recurse down a level and add parens to 'obj.method arg'
84
+ # however, 'not x' also parses as (send x :!)
85
+
86
+ if node.loc.selector.source == '!'
87
+ node = receiver
88
+ _receiver, _method_name, *args = *node
89
+ elsif node.loc.selector.source == 'not'
90
+ return correct_other(node, corrector)
91
+ else
92
+ fail 'unrecognized unary negation operator'
93
+ end
94
+ end
95
+ return unless correctable_send?(node)
96
+
97
+ sb = node.loc.expression.source_buffer
98
+ begin_paren = node.loc.selector.end_pos
99
+ range = Parser::Source::Range.new(sb, begin_paren, begin_paren + 1)
100
+ corrector.replace(range, '(')
101
+ corrector.insert_after(args.last.loc.expression, ')')
102
+ end
103
+
104
+ def correct_other(node, corrector)
105
+ return unless node.loc.expression.begin.source != '('
106
+ corrector.insert_before(node.loc.expression, '(')
107
+ corrector.insert_after(node.loc.expression, ')')
108
+ end
109
+
110
+ def correctable_send?(node)
111
+ _receiver, method_name, *args = *node
83
112
  # don't clobber if we already have a starting paren
84
- return false unless !expr.loc.begin || expr.loc.begin.source != '('
113
+ return false unless !node.loc.begin || node.loc.begin.source != '('
85
114
  # don't touch anything unless we are sure it is a method call.
86
115
  return false unless args.last && method_name.to_s =~ /[a-z]/
87
116
 
@@ -25,7 +25,7 @@ module RuboCop
25
25
  ]
26
26
 
27
27
  def on_send(node)
28
- receiver_node, method_name, *_arg_nodes = *node
28
+ receiver_node, method_name, *arg_nodes = *node
29
29
 
30
30
  TARGET_METHODS.each do |(target_class, target_method)|
31
31
  target_receiver = s(:const, nil, target_class)
@@ -33,6 +33,7 @@ module RuboCop
33
33
  next if receiver_node != target_receiver
34
34
  next if method_name != target_method
35
35
  next if node.parent && node.parent.block_type?
36
+ next if !arg_nodes.empty? && arg_nodes.last.block_pass_type?
36
37
 
37
38
  add_offense(node,
38
39
  :expression,
@@ -6,6 +6,8 @@ module RuboCop
6
6
  # This cop looks for uses of block comments (=begin...=end).
7
7
  class BlockComments < Cop
8
8
  MSG = 'Do not use block comments.'
9
+ BEGIN_LENGTH = "=begin\n".length
10
+ END_LENGTH = "\n=end".length
9
11
 
10
12
  def investigate(processed_source)
11
13
  processed_source.comments.each do |comment|
@@ -33,9 +35,9 @@ module RuboCop
33
35
 
34
36
  def parts(comment)
35
37
  expr = comment.loc.expression
36
- eq_begin = expr.resize("=begin\n".length)
38
+ eq_begin = expr.resize(BEGIN_LENGTH)
37
39
  eq_end = Parser::Source::Range.new(expr.source_buffer,
38
- expr.end_pos - "\n=end".length,
40
+ expr.end_pos - END_LENGTH,
39
41
  expr.end_pos)
40
42
  contents = Parser::Source::Range.new(expr.source_buffer,
41
43
  eq_begin.end_pos,