rubocop 1.30.0 → 1.31.1

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 (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