rubocop 1.30.0 → 1.31.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/config/default.yml +41 -8
  4. data/config/obsoletion.yml +2 -0
  5. data/exe/rubocop +15 -7
  6. data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
  7. data/lib/rubocop/cli/command/suggest_extensions.rb +3 -3
  8. data/lib/rubocop/config.rb +4 -0
  9. data/lib/rubocop/config_loader.rb +1 -0
  10. data/lib/rubocop/config_validator.rb +9 -5
  11. data/lib/rubocop/cop/base.rb +4 -0
  12. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  13. data/lib/rubocop/cop/bundler/gem_filename.rb +4 -4
  14. data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -2
  15. data/lib/rubocop/cop/corrector.rb +2 -2
  16. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +3 -3
  17. data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +1 -1
  18. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +31 -16
  19. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -1
  20. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  21. data/lib/rubocop/cop/gemspec/require_mfa.rb +20 -20
  22. data/lib/rubocop/cop/generator.rb +1 -1
  23. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -5
  24. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  25. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  26. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  27. data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
  28. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +25 -4
  29. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +4 -4
  30. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +9 -9
  31. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +9 -9
  32. data/lib/rubocop/cop/layout/first_argument_indentation.rb +27 -27
  33. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +17 -11
  34. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +49 -10
  35. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  36. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +68 -0
  37. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +130 -0
  38. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
  39. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
  40. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -2
  41. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  42. data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
  43. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -1
  44. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  45. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +10 -10
  46. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -3
  47. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +7 -7
  48. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  49. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +51 -0
  50. data/lib/rubocop/cop/lint/interpolation_check.rb +1 -1
  51. data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -0
  52. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +122 -0
  53. data/lib/rubocop/cop/lint/number_conversion.rb +3 -3
  54. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  55. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +5 -5
  56. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  57. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -1
  58. data/lib/rubocop/cop/lint/regexp_as_condition.rb +2 -2
  59. data/lib/rubocop/cop/lint/struct_new_override.rb +2 -2
  60. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  61. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +44 -0
  62. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  63. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +41 -12
  64. data/lib/rubocop/cop/mixin/range_help.rb +7 -3
  65. data/lib/rubocop/cop/naming/accessor_method_name.rb +3 -1
  66. data/lib/rubocop/cop/naming/variable_number.rb +17 -17
  67. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
  68. data/lib/rubocop/cop/style/and_or.rb +8 -8
  69. data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -1
  70. data/lib/rubocop/cop/style/block_delimiters.rb +4 -2
  71. data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
  72. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -0
  73. data/lib/rubocop/cop/style/empty_else.rb +10 -10
  74. data/lib/rubocop/cop/style/empty_method.rb +16 -1
  75. data/lib/rubocop/cop/style/encoding.rb +1 -1
  76. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  77. data/lib/rubocop/cop/style/fetch_env_var.rb +9 -2
  78. data/lib/rubocop/cop/style/format_string_token.rb +48 -17
  79. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  80. data/lib/rubocop/cop/style/guard_clause.rb +8 -6
  81. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -1
  82. data/lib/rubocop/cop/style/hash_except.rb +88 -8
  83. data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
  84. data/lib/rubocop/cop/style/implicit_runtime_error.rb +2 -2
  85. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  86. data/lib/rubocop/cop/style/line_end_concatenation.rb +1 -1
  87. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  88. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
  89. data/lib/rubocop/cop/style/missing_else.rb +24 -24
  90. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -2
  91. data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
  92. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -3
  93. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
  94. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
  95. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -3
  96. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  97. data/lib/rubocop/cop/style/nested_ternary_operator.rb +19 -7
  98. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  99. data/lib/rubocop/cop/style/not.rb +1 -1
  100. data/lib/rubocop/cop/style/redundant_argument.rb +1 -1
  101. data/lib/rubocop/cop/style/redundant_return.rb +1 -1
  102. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
  103. data/lib/rubocop/cop/style/rescue_standard_error.rb +10 -10
  104. data/lib/rubocop/cop/style/safe_navigation.rb +3 -0
  105. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  106. data/lib/rubocop/cop/style/string_concatenation.rb +5 -6
  107. data/lib/rubocop/cop/style/struct_inheritance.rb +2 -2
  108. data/lib/rubocop/cop/style/swap_values.rb +1 -1
  109. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  110. data/lib/rubocop/cop/style/unpack_first.rb +1 -1
  111. data/lib/rubocop/cop/util.rb +1 -1
  112. data/lib/rubocop/cops_documentation_generator.rb +18 -1
  113. data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -5
  114. data/lib/rubocop/formatter/formatter_set.rb +20 -19
  115. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +15 -2
  116. data/lib/rubocop/formatter/html_formatter.rb +0 -1
  117. data/lib/rubocop/formatter/offense_count_formatter.rb +2 -0
  118. data/lib/rubocop/formatter/simple_text_formatter.rb +6 -7
  119. data/lib/rubocop/formatter.rb +31 -0
  120. data/lib/rubocop/options.rb +25 -2
  121. data/lib/rubocop/rake_task.rb +30 -9
  122. data/lib/rubocop/runner.rb +2 -2
  123. data/lib/rubocop/server/cache.rb +109 -0
  124. data/lib/rubocop/server/cli.rb +104 -0
  125. data/lib/rubocop/server/client_command/base.rb +44 -0
  126. data/lib/rubocop/server/client_command/exec.rb +59 -0
  127. data/lib/rubocop/server/client_command/restart.rb +25 -0
  128. data/lib/rubocop/server/client_command/start.rb +43 -0
  129. data/lib/rubocop/server/client_command/status.rb +28 -0
  130. data/lib/rubocop/server/client_command/stop.rb +31 -0
  131. data/lib/rubocop/server/client_command.rb +26 -0
  132. data/lib/rubocop/server/core.rb +79 -0
  133. data/lib/rubocop/server/errors.rb +23 -0
  134. data/lib/rubocop/server/helper.rb +34 -0
  135. data/lib/rubocop/server/server_command/base.rb +50 -0
  136. data/lib/rubocop/server/server_command/exec.rb +34 -0
  137. data/lib/rubocop/server/server_command/stop.rb +24 -0
  138. data/lib/rubocop/server/server_command.rb +21 -0
  139. data/lib/rubocop/server/socket_reader.rb +65 -0
  140. data/lib/rubocop/server.rb +53 -0
  141. data/lib/rubocop/version.rb +15 -8
  142. data/lib/rubocop.rb +7 -26
  143. metadata +42 -5
  144. data/lib/rubocop/cop/gemspec/date_assignment.rb +0 -49
@@ -6,6 +6,15 @@ module RuboCop
6
6
  # Checks if empty lines around the bodies of classes match
7
7
  # the configuration.
8
8
  #
9
+ # @example EnforcedStyle: no_empty_lines (default)
10
+ # # good
11
+ #
12
+ # class Foo
13
+ # def bar
14
+ # # ...
15
+ # end
16
+ # end
17
+ #
9
18
  # @example EnforcedStyle: empty_lines
10
19
  # # good
11
20
  #
@@ -55,15 +64,6 @@ module RuboCop
55
64
  # end
56
65
  #
57
66
  # end
58
- #
59
- # @example EnforcedStyle: no_empty_lines (default)
60
- # # good
61
- #
62
- # class Foo
63
- # def bar
64
- # # ...
65
- # end
66
- # end
67
67
  class EmptyLinesAroundClassBody < Base
68
68
  include EmptyLinesAroundBody
69
69
  extend AutoCorrector
@@ -6,6 +6,15 @@ module RuboCop
6
6
  # Checks if empty lines around the bodies of modules match
7
7
  # the configuration.
8
8
  #
9
+ # @example EnforcedStyle: no_empty_lines (default)
10
+ # # good
11
+ #
12
+ # module Foo
13
+ # def bar
14
+ # # ...
15
+ # end
16
+ # end
17
+ #
9
18
  # @example EnforcedStyle: empty_lines
10
19
  # # good
11
20
  #
@@ -35,15 +44,6 @@ module RuboCop
35
44
  # def bar; end
36
45
  #
37
46
  # end
38
- #
39
- # @example EnforcedStyle: no_empty_lines (default)
40
- # # good
41
- #
42
- # module Foo
43
- # def bar
44
- # # ...
45
- # end
46
- # end
47
47
  class EmptyLinesAroundModuleBody < Base
48
48
  include EmptyLinesAroundBody
49
49
  extend AutoCorrector
@@ -37,9 +37,10 @@ module RuboCop
37
37
  # nested_first_param),
38
38
  # second_param
39
39
  #
40
- # @example EnforcedStyle: consistent
41
- # # The first argument should always be indented one step more than the
42
- # # preceding line.
40
+ # @example EnforcedStyle: special_for_inner_method_call_in_parentheses (default)
41
+ # # Same as `special_for_inner_method_call` except that the special rule
42
+ # # only applies if the outer method call encloses its arguments in
43
+ # # parentheses.
43
44
  #
44
45
  # # good
45
46
  # some_method(
@@ -51,7 +52,7 @@ module RuboCop
51
52
  # second_param)
52
53
  #
53
54
  # foo = some_method(nested_call(
54
- # nested_first_param),
55
+ # nested_first_param),
55
56
  # second_param)
56
57
  #
57
58
  # foo = some_method(
@@ -63,9 +64,9 @@ module RuboCop
63
64
  # nested_first_param),
64
65
  # second_param
65
66
  #
66
- # @example EnforcedStyle: consistent_relative_to_receiver
67
- # # The first argument should always be indented one level relative to
68
- # # the parent that is receiving the argument
67
+ # @example EnforcedStyle: consistent
68
+ # # The first argument should always be indented one step more than the
69
+ # # preceding line.
69
70
  #
70
71
  # # good
71
72
  # some_method(
@@ -73,27 +74,25 @@ module RuboCop
73
74
  # second_param)
74
75
  #
75
76
  # foo = some_method(
76
- # first_param,
77
+ # first_param,
77
78
  # second_param)
78
79
  #
79
80
  # foo = some_method(nested_call(
80
- # nested_first_param),
81
+ # nested_first_param),
81
82
  # second_param)
82
83
  #
83
84
  # foo = some_method(
84
- # nested_call(
85
- # nested_first_param),
85
+ # nested_call(
86
+ # nested_first_param),
86
87
  # second_param)
87
88
  #
88
89
  # some_method nested_call(
89
- # nested_first_param),
90
- # second_params
90
+ # nested_first_param),
91
+ # second_param
91
92
  #
92
- # @example EnforcedStyle: special_for_inner_method_call
93
- # # The first argument should normally be indented one step more than
94
- # # the preceding line, but if it's a argument for a method call that
95
- # # is itself a argument in a method call, then the inner argument
96
- # # should be indented relative to the inner method.
93
+ # @example EnforcedStyle: consistent_relative_to_receiver
94
+ # # The first argument should always be indented one level relative to
95
+ # # the parent that is receiving the argument
97
96
  #
98
97
  # # good
99
98
  # some_method(
@@ -101,7 +100,7 @@ module RuboCop
101
100
  # second_param)
102
101
  #
103
102
  # foo = some_method(
104
- # first_param,
103
+ # first_param,
105
104
  # second_param)
106
105
  #
107
106
  # foo = some_method(nested_call(
@@ -109,18 +108,19 @@ module RuboCop
109
108
  # second_param)
110
109
  #
111
110
  # foo = some_method(
112
- # nested_call(
113
- # nested_first_param),
111
+ # nested_call(
112
+ # nested_first_param),
114
113
  # second_param)
115
114
  #
116
115
  # some_method nested_call(
117
116
  # nested_first_param),
118
- # second_param
117
+ # second_params
119
118
  #
120
- # @example EnforcedStyle: special_for_inner_method_call_in_parentheses (default)
121
- # # Same as `special_for_inner_method_call` except that the special rule
122
- # # only applies if the outer method call encloses its arguments in
123
- # # parentheses.
119
+ # @example EnforcedStyle: special_for_inner_method_call
120
+ # # The first argument should normally be indented one step more than
121
+ # # the preceding line, but if it's a argument for a method call that
122
+ # # is itself a argument in a method call, then the inner argument
123
+ # # should be indented relative to the inner method.
124
124
  #
125
125
  # # good
126
126
  # some_method(
@@ -141,7 +141,7 @@ module RuboCop
141
141
  # second_param)
142
142
  #
143
143
  # some_method nested_call(
144
- # nested_first_param),
144
+ # nested_first_param),
145
145
  # second_param
146
146
  #
147
147
  class FirstArgumentIndentation < Base
@@ -127,22 +127,25 @@ module RuboCop
127
127
  # if the right bracket is on the same line as the last value, accept
128
128
  return if /\S/.match?(right_bracket.source_line[0...right_bracket.column])
129
129
 
130
- expected_column = base_column(left_bracket, left_parenthesis)
130
+ expected_column, indent_base_type = indent_base(left_bracket, left_parenthesis)
131
131
  @column_delta = expected_column - right_bracket.column
132
132
  return if @column_delta.zero?
133
133
 
134
- msg = msg(left_parenthesis)
134
+ msg = message_for_right_bracket(indent_base_type)
135
135
  add_offense(right_bracket, message: msg) do |corrector|
136
136
  autocorrect(corrector, right_bracket)
137
137
  end
138
138
  end
139
139
 
140
140
  # Returns the description of what the correct indentation is based on.
141
- def base_description(left_parenthesis)
142
- if style == :align_brackets
141
+ def base_description(indent_base_type)
142
+ case indent_base_type
143
+ when :left_brace_or_bracket
143
144
  'the position of the opening bracket'
144
- elsif left_parenthesis && style == :special_inside_parentheses
145
+ when :first_colmn_after_left_parenthesis
145
146
  'the first position after the preceding left parenthesis'
147
+ when :parent_hash_key
148
+ 'the parent hash key'
146
149
  else
147
150
  'the start of the line where the left square bracket is'
148
151
  end
@@ -156,15 +159,18 @@ module RuboCop
156
159
  )
157
160
  end
158
161
 
159
- def msg(left_parenthesis)
160
- if style == :align_brackets
162
+ def message_for_right_bracket(indent_base_type)
163
+ case indent_base_type
164
+ when :left_brace_or_bracket
161
165
  'Indent the right bracket the same as the left bracket.'
162
- elsif style == :special_inside_parentheses && left_parenthesis
166
+ when :first_colmn_after_left_parenthesis
163
167
  'Indent the right bracket the same as the first position ' \
164
- 'after the preceding left parenthesis.'
168
+ 'after the preceding left parenthesis.'
169
+ when :parent_hash_key
170
+ 'Indent the right bracket the same as the parent hash key.' \
165
171
  else
166
- 'Indent the right bracket the same as the start of the line' \
167
- ' where the left bracket is.'
172
+ 'Indent the right bracket the same as the start of the line ' \
173
+ 'where the left bracket is.'
168
174
  end
169
175
  end
170
176
  end
@@ -32,6 +32,14 @@ module RuboCop
32
32
  # and_in_a_method_call({
33
33
  # no: :difference
34
34
  # })
35
+ # takes_multi_pairs_hash(x: {
36
+ # a: 1,
37
+ # b: 2
38
+ # },
39
+ # y: {
40
+ # c: 1,
41
+ # d: 2
42
+ # })
35
43
  #
36
44
  # # good
37
45
  # special_inside_parentheses
@@ -41,6 +49,14 @@ module RuboCop
41
49
  # but_in_a_method_call({
42
50
  # its_like: :this
43
51
  # })
52
+ # takes_multi_pairs_hash(x: {
53
+ # a: 1,
54
+ # b: 2
55
+ # },
56
+ # y: {
57
+ # c: 1,
58
+ # d: 2
59
+ # })
44
60
  #
45
61
  # @example EnforcedStyle: consistent
46
62
  # # The `consistent` style enforces that the first key in a hash
@@ -64,6 +80,7 @@ module RuboCop
64
80
  # no: :difference
65
81
  # })
66
82
  #
83
+ #
67
84
  # @example EnforcedStyle: align_braces
68
85
  # # The `align_brackets` style enforces that the opening and closing
69
86
  # # braces are indented to the same position.
@@ -72,11 +89,27 @@ module RuboCop
72
89
  # and_now_for_something = {
73
90
  # completely: :different
74
91
  # }
92
+ # takes_multi_pairs_hash(x: {
93
+ # a: 1,
94
+ # b: 2
95
+ # },
96
+ # y: {
97
+ # c: 1,
98
+ # d: 2
99
+ # })
75
100
  #
76
101
  # # good
77
102
  # and_now_for_something = {
78
103
  # completely: :different
79
104
  # }
105
+ # takes_multi_pairs_hash(x: {
106
+ # a: 1,
107
+ # b: 2
108
+ # },
109
+ # y: {
110
+ # c: 1,
111
+ # d: 2
112
+ # })
80
113
  class FirstHashElementIndentation < Base
81
114
  include Alignment
82
115
  include ConfigurableEnforcedStyle
@@ -132,11 +165,11 @@ module RuboCop
132
165
  # if the right brace is on the same line as the last value, accept
133
166
  return if /\S/.match?(right_brace.source_line[0...right_brace.column])
134
167
 
135
- expected_column = base_column(left_brace, left_parenthesis)
168
+ expected_column, indent_base_type = indent_base(left_brace, left_parenthesis)
136
169
  @column_delta = expected_column - right_brace.column
137
170
  return if @column_delta.zero?
138
171
 
139
- message = message_for_right_brace(left_parenthesis)
172
+ message = message_for_right_brace(indent_base_type)
140
173
  add_offense(right_brace, message: message) do |corrector|
141
174
  autocorrect(corrector, right_brace)
142
175
  end
@@ -155,11 +188,14 @@ module RuboCop
155
188
  end
156
189
 
157
190
  # Returns the description of what the correct indentation is based on.
158
- def base_description(left_parenthesis)
159
- if style == :align_braces
191
+ def base_description(indent_base_type)
192
+ case indent_base_type
193
+ when :left_brace_or_bracket
160
194
  'the position of the opening brace'
161
- elsif left_parenthesis && style == :special_inside_parentheses
195
+ when :first_colmn_after_left_parenthesis
162
196
  'the first position after the preceding left parenthesis'
197
+ when :parent_hash_key
198
+ 'the parent hash key'
163
199
  else
164
200
  'the start of the line where the left curly brace is'
165
201
  end
@@ -173,15 +209,18 @@ module RuboCop
173
209
  )
174
210
  end
175
211
 
176
- def message_for_right_brace(left_parenthesis)
177
- if style == :align_braces
212
+ def message_for_right_brace(indent_base_type)
213
+ case indent_base_type
214
+ when :left_brace_or_bracket
178
215
  'Indent the right brace the same as the left brace.'
179
- elsif style == :special_inside_parentheses && left_parenthesis
216
+ when :first_colmn_after_left_parenthesis
180
217
  'Indent the right brace the same as the first position ' \
181
- 'after the preceding left parenthesis.'
218
+ 'after the preceding left parenthesis.'
219
+ when :parent_hash_key
220
+ 'Indent the right brace the same as the parent hash key.'
182
221
  else
183
222
  'Indent the right brace the same as the start of the line ' \
184
- 'where the left brace is.'
223
+ 'where the left brace is.'
185
224
  end
186
225
  end
187
226
 
@@ -41,7 +41,7 @@ module RuboCop
41
41
  return unless token
42
42
  return if token.column.zero?
43
43
 
44
- space_range = range_with_surrounding_space(range: token.pos, side: :left, newlines: false)
44
+ space_range = range_with_surrounding_space(token.pos, side: :left, newlines: false)
45
45
  # If the file starts with a byte order mark (BOM), the column can be
46
46
  # non-zero, but then we find out here if there's no space to the left
47
47
  # of the first token.
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Layout
6
+ # Checks that strings broken over multiple lines (by a backslash) contain
7
+ # trailing spaces instead of leading spaces.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # 'this text contains a lot of' \
12
+ # ' spaces'
13
+ #
14
+ # # good
15
+ # 'this text contains a lot of ' \
16
+ # 'spaces'
17
+ #
18
+ # # bad
19
+ # 'this text is too' \
20
+ # ' long'
21
+ #
22
+ # # good
23
+ # 'this text is too ' \
24
+ # 'long'
25
+ #
26
+ class LineContinuationLeadingSpace < Base
27
+ include RangeHelp
28
+
29
+ MSG = 'Move leading spaces to the end of previous line.'
30
+
31
+ def on_dstr(node)
32
+ range_start = node.loc.expression.begin_pos - node.loc.expression.column
33
+
34
+ raw_lines(node).each_cons(2) do |raw_line_one, raw_line_two|
35
+ range_start += raw_line_one.length
36
+
37
+ investigate(raw_line_one, raw_line_two, range_start)
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def raw_lines(node)
44
+ processed_source.raw_source.lines[node.first_line - 1, line_range(node).size]
45
+ end
46
+
47
+ def investigate(first_line, second_line, range_start)
48
+ return unless continuation?(first_line)
49
+
50
+ matches = second_line.match(/\A(?<indent>\s*['"])(?<leading_spaces>\s+)/)
51
+ return if matches.nil?
52
+
53
+ add_offense(offense_range(range_start, matches))
54
+ end
55
+
56
+ def continuation?(line)
57
+ line.end_with?("\\\n")
58
+ end
59
+
60
+ def offense_range(range_start, matches)
61
+ begin_pos = range_start + matches[:indent].length
62
+ end_pos = begin_pos + matches[:leading_spaces].length
63
+ range_between(begin_pos, end_pos)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Layout
6
+ # Checks that the backslash of a line continuation is separated from
7
+ # preceding text by exactly one space (default) or zero spaces.
8
+ #
9
+ # @example EnforcedStyle: space (default)
10
+ # # bad
11
+ # 'a'\
12
+ # 'b' \
13
+ # 'c'
14
+ #
15
+ # # good
16
+ # 'a' \
17
+ # 'b' \
18
+ # 'c'
19
+ #
20
+ # @example EnforcedStyle: no_space
21
+ # # bad
22
+ # 'a' \
23
+ # 'b' \
24
+ # 'c'
25
+ #
26
+ # # good
27
+ # 'a'\
28
+ # 'b'\
29
+ # 'c'
30
+ class LineContinuationSpacing < Base
31
+ include RangeHelp
32
+ extend AutoCorrector
33
+
34
+ def on_new_investigation
35
+ last_line = last_line(processed_source)
36
+
37
+ @ignored_ranges = string_literal_ranges(processed_source.ast) +
38
+ comment_ranges(processed_source.comments)
39
+
40
+ processed_source.raw_source.lines.each_with_index do |line, index|
41
+ break if index >= last_line
42
+
43
+ line_number = index + 1
44
+ investigate(line, line_number)
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def investigate(line, line_number)
51
+ offensive_spacing = find_offensive_spacing(line)
52
+ return unless offensive_spacing
53
+
54
+ range = source_range(
55
+ processed_source.buffer,
56
+ line_number,
57
+ line.length - offensive_spacing.length - 1,
58
+ offensive_spacing.length
59
+ )
60
+
61
+ return if ignore_range?(range)
62
+
63
+ add_offense(range) { |corrector| autocorrect(corrector, range) }
64
+ end
65
+
66
+ def find_offensive_spacing(line)
67
+ if no_space_style?
68
+ line[/\s+\\$/, 0]
69
+ elsif space_style?
70
+ line[/((?<!\s)|\s{2,})\\$/, 0]
71
+ end
72
+ end
73
+
74
+ def message(_range)
75
+ if no_space_style?
76
+ 'Use zero spaces in front of backslash.'
77
+ elsif space_style?
78
+ 'Use one space in front of backslash.'
79
+ end
80
+ end
81
+
82
+ def autocorrect(corrector, range)
83
+ correction = if no_space_style?
84
+ '\\'
85
+ elsif space_style?
86
+ ' \\'
87
+ end
88
+ corrector.replace(range, correction)
89
+ end
90
+
91
+ def string_literal_ranges(ast)
92
+ # which lines start inside a string literal?
93
+ return [] if ast.nil?
94
+
95
+ ast.each_node(:str, :dstr).each_with_object(Set.new) do |str, ranges|
96
+ loc = str.location
97
+
98
+ if str.heredoc?
99
+ ranges << loc.heredoc_body
100
+ elsif loc.respond_to?(:begin) && loc.begin
101
+ ranges << loc.expression
102
+ end
103
+ end
104
+ end
105
+
106
+ def comment_ranges(comments)
107
+ comments.map(&:loc).map(&:expression)
108
+ end
109
+
110
+ def last_line(processed_source)
111
+ last_token = processed_source.tokens.last
112
+
113
+ last_token ? last_token.line : processed_source.lines.length
114
+ end
115
+
116
+ def ignore_range?(backtick_range)
117
+ @ignored_ranges.any? { |range| range.contains?(backtick_range) }
118
+ end
119
+
120
+ def no_space_style?
121
+ cop_config['EnforcedStyle'] == 'no_space'
122
+ end
123
+
124
+ def space_style?
125
+ cop_config['EnforcedStyle'] == 'space'
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -117,7 +117,7 @@ module RuboCop
117
117
 
118
118
  def autocorrect_arguments(corrector, node)
119
119
  end_pos = range_with_surrounding_space(
120
- range: node.arguments.source_range,
120
+ node.arguments.source_range,
121
121
  side: :right,
122
122
  newlines: false
123
123
  ).end_pos
@@ -56,8 +56,8 @@ module RuboCop
56
56
  return unless style == :aligned && cop_config['IndentationWidth']
57
57
 
58
58
  raise ValidationError,
59
- 'The `Layout/MultilineMethodCallIndentation`' \
60
- ' cop only accepts an `IndentationWidth` ' \
59
+ 'The `Layout/MultilineMethodCallIndentation` ' \
60
+ 'cop only accepts an `IndentationWidth` ' \
61
61
  'configuration parameter when ' \
62
62
  '`EnforcedStyle` is `indented`.'
63
63
  end
@@ -57,8 +57,8 @@ module RuboCop
57
57
  def validate_config
58
58
  return unless style == :aligned && cop_config['IndentationWidth']
59
59
 
60
- raise ValidationError, 'The `Layout/MultilineOperationIndentation`' \
61
- ' cop only accepts an `IndentationWidth` ' \
60
+ raise ValidationError, 'The `Layout/MultilineOperationIndentation` ' \
61
+ 'cop only accepts an `IndentationWidth` ' \
62
62
  'configuration parameter when ' \
63
63
  '`EnforcedStyle` is `indented`.'
64
64
  end
@@ -127,7 +127,7 @@ module RuboCop
127
127
 
128
128
  expr = arg.source_range
129
129
  check_no_space(
130
- range_with_surrounding_space(range: expr, side: :left).begin_pos,
130
+ range_with_surrounding_space(expr, side: :left).begin_pos,
131
131
  expr.begin_pos - 1,
132
132
  'Extra space before'
133
133
  )
@@ -161,7 +161,7 @@ module RuboCop
161
161
  end
162
162
 
163
163
  def check_operator(type, operator, right_operand)
164
- with_space = range_with_surrounding_space(range: operator)
164
+ with_space = range_with_surrounding_space(operator)
165
165
  return if with_space.source.start_with?("\n")
166
166
 
167
167
  offense(type, operator, with_space, right_operand) do |msg|
@@ -65,7 +65,7 @@ module RuboCop
65
65
  return if conflict_with_block_delimiters?(node)
66
66
 
67
67
  left_brace = node.loc.begin
68
- space_plus_brace = range_with_surrounding_space(range: left_brace)
68
+ space_plus_brace = range_with_surrounding_space(left_brace)
69
69
  used_style =
70
70
  space_plus_brace.source.start_with?('{') ? :no_space : :space
71
71
 
@@ -36,7 +36,7 @@ module RuboCop
36
36
  return unless regular_method_call_with_arguments?(node)
37
37
 
38
38
  first_arg = node.first_argument.source_range
39
- first_arg_with_space = range_with_surrounding_space(range: first_arg, side: :left)
39
+ first_arg_with_space = range_with_surrounding_space(first_arg, side: :left)
40
40
  space = range_between(first_arg_with_space.begin_pos, first_arg.begin_pos)
41
41
  return if space.length == 1
42
42
  return unless expect_params_after_method_name?(node)
@@ -6,16 +6,6 @@ module RuboCop
6
6
  # Checks that brackets used for array literals have or don't have
7
7
  # surrounding space depending on configuration.
8
8
  #
9
- # @example EnforcedStyle: space
10
- # # The `space` style enforces that array literals have
11
- # # surrounding space.
12
- #
13
- # # bad
14
- # array = [a, b, c, d]
15
- #
16
- # # good
17
- # array = [ a, b, c, d ]
18
- #
19
9
  # @example EnforcedStyle: no_space (default)
20
10
  # # The `no_space` style enforces that array literals have
21
11
  # # no surrounding space.
@@ -26,6 +16,16 @@ module RuboCop
26
16
  # # good
27
17
  # array = [a, b, c, d]
28
18
  #
19
+ # @example EnforcedStyle: space
20
+ # # The `space` style enforces that array literals have
21
+ # # surrounding space.
22
+ #
23
+ # # bad
24
+ # array = [a, b, c, d]
25
+ #
26
+ # # good
27
+ # array = [ a, b, c, d ]
28
+ #
29
29
  # @example EnforcedStyle: compact
30
30
  # # The `compact` style normally requires a space inside
31
31
  # # array brackets, with the exception that successive left