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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +315 -0
- data/README.md +199 -38
- data/config/default.yml +91 -12
- data/config/disabled.yml +45 -4
- data/config/enabled.yml +107 -9
- data/lib/rubocop/ast_node.rb +48 -0
- data/lib/rubocop/cli.rb +11 -1
- data/lib/rubocop/comment_config.rb +4 -1
- data/lib/rubocop/config.rb +26 -17
- data/lib/rubocop/config_loader.rb +61 -14
- data/lib/rubocop/cop/commissioner.rb +7 -12
- data/lib/rubocop/cop/cop.rb +43 -20
- data/lib/rubocop/cop/lint/block_alignment.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +69 -0
- data/lib/rubocop/cop/lint/debugger.rb +9 -48
- data/lib/rubocop/cop/lint/def_end_alignment.rb +8 -4
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +42 -23
- data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
- data/lib/rubocop/cop/lint/duplicated_key.rb +37 -0
- data/lib/rubocop/cop/lint/end_alignment.rb +33 -13
- data/lib/rubocop/cop/lint/eval.rb +6 -2
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +175 -0
- data/lib/rubocop/cop/lint/literal_in_condition.rb +0 -5
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +10 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +31 -0
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +19 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/lint/unneeded_disable.rb +72 -0
- data/lib/rubocop/cop/lint/unused_block_argument.rb +6 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +8 -0
- data/lib/rubocop/cop/metrics/abc_size.rb +17 -6
- data/lib/rubocop/cop/metrics/class_length.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +1 -3
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- data/lib/rubocop/cop/metrics/parameter_lists.rb +1 -1
- data/lib/rubocop/cop/mixin/access_modifier_node.rb +1 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -2
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +28 -4
- data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +26 -3
- data/lib/rubocop/cop/mixin/check_assignment.rb +2 -3
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +59 -12
- data/lib/rubocop/cop/mixin/configurable_max.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_naming.rb +14 -3
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -3
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +10 -1
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +41 -0
- data/lib/rubocop/cop/mixin/if_node.rb +10 -0
- data/lib/rubocop/cop/mixin/method_preference.rb +28 -0
- data/lib/rubocop/cop/mixin/negative_conditional.rb +1 -1
- data/lib/rubocop/cop/mixin/on_method_def.rb +4 -5
- data/lib/rubocop/cop/mixin/safe_assignment.rb +3 -14
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +8 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +8 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +4 -7
- data/lib/rubocop/cop/mixin/string_help.rb +1 -1
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +5 -4
- data/lib/rubocop/cop/offense.rb +16 -3
- data/lib/rubocop/cop/performance/case_when_splat.rb +160 -0
- data/lib/rubocop/cop/performance/count.rb +35 -30
- data/lib/rubocop/cop/performance/detect.rb +16 -3
- data/lib/rubocop/cop/performance/fixed_size.rb +50 -0
- data/lib/rubocop/cop/performance/flat_map.rb +3 -3
- data/lib/rubocop/cop/performance/sample.rb +103 -59
- data/lib/rubocop/cop/performance/size.rb +2 -1
- data/lib/rubocop/cop/performance/string_replacement.rb +187 -0
- data/lib/rubocop/cop/rails/action_filter.rb +31 -5
- data/lib/rubocop/cop/rails/date.rb +15 -14
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +97 -0
- data/lib/rubocop/cop/rails/read_write_attribute.rb +1 -1
- data/lib/rubocop/cop/rails/time_zone.rb +46 -18
- data/lib/rubocop/cop/style/alias.rb +1 -0
- data/lib/rubocop/cop/style/align_hash.rb +8 -15
- data/lib/rubocop/cop/style/align_parameters.rb +19 -7
- data/lib/rubocop/cop/style/and_or.rb +42 -13
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +2 -1
- data/lib/rubocop/cop/style/block_comments.rb +4 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +69 -24
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +40 -12
- data/lib/rubocop/cop/style/case_indentation.rb +18 -4
- data/lib/rubocop/cop/style/collection_methods.rb +2 -20
- data/lib/rubocop/cop/style/command_literal.rb +2 -10
- data/lib/rubocop/cop/style/comment_annotation.rb +29 -8
- data/lib/rubocop/cop/style/copyright.rb +5 -3
- data/lib/rubocop/cop/style/documentation.rb +21 -12
- data/lib/rubocop/cop/style/dot_position.rb +6 -0
- data/lib/rubocop/cop/style/double_negation.rb +4 -15
- data/lib/rubocop/cop/style/each_with_object.rb +17 -4
- data/lib/rubocop/cop/style/else_alignment.rb +2 -1
- data/lib/rubocop/cop/style/empty_else.rb +25 -0
- data/lib/rubocop/cop/style/empty_line_between_defs.rb +39 -14
- data/lib/rubocop/cop/style/encoding.rb +10 -4
- data/lib/rubocop/cop/style/extra_spacing.rb +126 -5
- data/lib/rubocop/cop/style/first_array_element_line_break.rb +41 -0
- data/lib/rubocop/cop/style/first_hash_element_line_break.rb +35 -0
- data/lib/rubocop/cop/style/first_method_argument_line_break.rb +37 -0
- data/lib/rubocop/cop/style/first_method_parameter_line_break.rb +42 -0
- data/lib/rubocop/cop/style/first_parameter_indentation.rb +5 -3
- data/lib/rubocop/cop/style/for.rb +2 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +5 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +32 -5
- data/lib/rubocop/cop/style/indent_hash.rb +67 -37
- data/lib/rubocop/cop/style/indentation_width.rb +36 -10
- data/lib/rubocop/cop/style/initial_indentation.rb +37 -0
- data/lib/rubocop/cop/style/leading_comment_space.rb +3 -2
- data/lib/rubocop/cop/style/method_call_parentheses.rb +28 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -7
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +21 -24
- data/lib/rubocop/cop/style/mutable_constant.rb +35 -0
- data/lib/rubocop/cop/style/nested_modifier.rb +97 -0
- data/lib/rubocop/cop/style/next.rb +50 -15
- data/lib/rubocop/cop/style/non_nil_check.rb +12 -8
- data/lib/rubocop/cop/style/one_line_conditional.rb +8 -4
- data/lib/rubocop/cop/style/option_hash.rb +64 -0
- data/lib/rubocop/cop/style/optional_arguments.rb +49 -0
- data/lib/rubocop/cop/style/parallel_assignment.rb +218 -0
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +3 -66
- data/lib/rubocop/cop/style/predicate_name.rb +7 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +2 -13
- data/lib/rubocop/cop/style/redundant_freeze.rb +37 -0
- data/lib/rubocop/cop/style/redundant_return.rb +32 -3
- data/lib/rubocop/cop/style/regexp_literal.rb +2 -10
- data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +81 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +30 -22
- data/lib/rubocop/cop/style/send.rb +18 -0
- data/lib/rubocop/cop/style/signal_exception.rb +24 -11
- data/lib/rubocop/cop/style/single_line_methods.rb +8 -9
- data/lib/rubocop/cop/style/single_space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/style/space_around_operators.rb +2 -0
- data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +61 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +4 -2
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +108 -0
- data/lib/rubocop/cop/style/string_methods.rb +32 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +11 -10
- data/lib/rubocop/cop/style/symbol_literal.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +62 -13
- data/lib/rubocop/cop/style/trailing_blank_lines.rb +9 -1
- data/lib/rubocop/cop/style/trailing_comma.rb +17 -7
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -2
- data/lib/rubocop/cop/style/trivial_accessors.rb +10 -1
- data/lib/rubocop/cop/style/unneeded_percent_q.rb +31 -20
- data/lib/rubocop/cop/style/variable_name.rb +5 -0
- data/lib/rubocop/cop/style/while_until_do.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +15 -2
- data/lib/rubocop/cop/team.rb +25 -5
- data/lib/rubocop/cop/util.rb +7 -2
- data/lib/rubocop/cop/variable_force/locatable.rb +6 -6
- data/lib/rubocop/cop/variable_force.rb +10 -10
- data/lib/rubocop/formatter/base_formatter.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +70 -8
- data/lib/rubocop/formatter/formatter_set.rb +27 -1
- data/lib/rubocop/formatter/progress_formatter.rb +10 -2
- data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
- data/lib/rubocop/node_pattern.rb +390 -0
- data/lib/rubocop/options.rb +148 -81
- data/lib/rubocop/processed_source.rb +7 -2
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +60 -0
- data/lib/rubocop/result_cache.rb +123 -0
- data/lib/rubocop/runner.rb +85 -22
- data/lib/rubocop/target_finder.rb +4 -4
- data/lib/rubocop/token.rb +2 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop/warning.rb +11 -0
- data/lib/rubocop.rb +32 -3
- data/relnotes/v0.32.0.md +139 -0
- data/relnotes/v0.32.1.md +122 -0
- data/relnotes/v0.33.0.md +157 -0
- data/relnotes/v0.34.0.md +182 -0
- data/relnotes/v0.34.1.md +129 -0
- data/relnotes/v0.34.2.md +139 -0
- data/relnotes/v0.35.0.md +210 -0
- data/rubocop.gemspec +4 -4
- metadata +50 -12
- 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 '
|
|
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 '
|
|
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 '
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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 == :
|
|
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 == :
|
|
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,
|
|
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 '
|
|
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 '
|
|
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
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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 &
|
|
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
|
-
|
|
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
|
-
"
|
|
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 &
|
|
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 == :
|
|
150
|
+
style == :flexible
|
|
144
151
|
end
|
|
145
152
|
|
|
146
153
|
def good_methods
|
|
147
|
-
style == :
|
|
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
|
|
@@ -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?
|
|
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
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
81
|
-
|
|
82
|
-
|
|
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 !
|
|
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, *
|
|
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(
|
|
38
|
+
eq_begin = expr.resize(BEGIN_LENGTH)
|
|
37
39
|
eq_end = Parser::Source::Range.new(expr.source_buffer,
|
|
38
|
-
expr.end_pos -
|
|
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,
|