rubocop 0.74.0 → 0.75.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/config/default.yml +27 -3
  4. data/lib/rubocop.rb +6 -1
  5. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +1 -12
  6. data/lib/rubocop/comment_config.rb +3 -2
  7. data/lib/rubocop/config.rb +4 -0
  8. data/lib/rubocop/config_loader.rb +20 -2
  9. data/lib/rubocop/config_loader_resolver.rb +2 -2
  10. data/lib/rubocop/config_obsoletion.rb +12 -0
  11. data/lib/rubocop/cop/autocorrect_logic.rb +2 -2
  12. data/lib/rubocop/cop/cop.rb +4 -3
  13. data/lib/rubocop/cop/correctors/alignment_corrector.rb +43 -17
  14. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +2 -2
  15. data/lib/rubocop/cop/generator.rb +3 -3
  16. data/lib/rubocop/cop/generator/configuration_injector.rb +9 -4
  17. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  18. data/lib/rubocop/cop/layout/block_alignment.rb +2 -2
  19. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
  20. data/lib/rubocop/cop/layout/extra_spacing.rb +0 -6
  21. data/lib/rubocop/cop/layout/indent_assignment.rb +9 -1
  22. data/lib/rubocop/cop/layout/indent_heredoc.rb +1 -1
  23. data/lib/rubocop/cop/layout/multiline_block_layout.rb +24 -2
  24. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +5 -1
  25. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +1 -1
  26. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +7 -0
  27. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +2 -0
  28. data/lib/rubocop/cop/lint/assignment_in_condition.rb +17 -4
  29. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  30. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +10 -36
  31. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  32. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +91 -0
  33. data/lib/rubocop/cop/lint/unneeded_cop_disable_directive.rb +1 -1
  34. data/lib/rubocop/cop/message_annotator.rb +16 -7
  35. data/lib/rubocop/cop/migration/department_name.rb +44 -0
  36. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  37. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  38. data/lib/rubocop/cop/mixin/safe_mode.rb +2 -0
  39. data/lib/rubocop/cop/naming/method_name.rb +12 -1
  40. data/lib/rubocop/cop/naming/variable_name.rb +1 -0
  41. data/lib/rubocop/cop/offense.rb +18 -7
  42. data/lib/rubocop/cop/registry.rb +22 -1
  43. data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -0
  44. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  45. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +29 -10
  46. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  47. data/lib/rubocop/cop/style/commented_keyword.rb +8 -2
  48. data/lib/rubocop/cop/style/conditional_assignment.rb +4 -4
  49. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +8 -2
  50. data/lib/rubocop/cop/style/format_string_token.rb +10 -40
  51. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +18 -33
  52. data/lib/rubocop/cop/style/if_unless_modifier.rb +51 -15
  53. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  54. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +5 -5
  55. data/lib/rubocop/cop/style/mixin_usage.rb +11 -1
  56. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  57. data/lib/rubocop/cop/style/nested_modifier.rb +18 -2
  58. data/lib/rubocop/cop/style/or_assignment.rb +6 -1
  59. data/lib/rubocop/cop/style/parentheses_around_condition.rb +14 -0
  60. data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -4
  61. data/lib/rubocop/cop/style/redundant_self.rb +18 -1
  62. data/lib/rubocop/cop/style/rescue_modifier.rb +24 -0
  63. data/lib/rubocop/cop/style/safe_navigation.rb +9 -0
  64. data/lib/rubocop/cop/style/single_line_methods.rb +8 -1
  65. data/lib/rubocop/cop/style/ternary_parentheses.rb +19 -0
  66. data/lib/rubocop/cop/utils/format_string.rb +128 -0
  67. data/lib/rubocop/cop/variable_force/variable.rb +15 -2
  68. data/lib/rubocop/core_ext/string.rb +0 -24
  69. data/lib/rubocop/formatter/emacs_style_formatter.rb +8 -5
  70. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  71. data/lib/rubocop/formatter/pacman_formatter.rb +80 -0
  72. data/lib/rubocop/formatter/simple_text_formatter.rb +9 -1
  73. data/lib/rubocop/formatter/tap_formatter.rb +9 -1
  74. data/lib/rubocop/magic_comment.rb +4 -0
  75. data/lib/rubocop/options.rb +2 -1
  76. data/lib/rubocop/runner.rb +14 -8
  77. data/lib/rubocop/version.rb +1 -1
  78. metadata +6 -3
  79. data/lib/rubocop/cop/mixin/ignored_method_patterns.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7299e4e21bbddcdbfec2725fec41c384d50867b70a986d87ea0f6f7f08dd3ebe
4
- data.tar.gz: 504dae598bbb526afed6bc9ecc56d86a27656d535bf52e30c85e7ab005af99f3
3
+ metadata.gz: 78f22d960f9c7b85730f215741a8e083b3b63396f414478d4831762e4c4cf7cb
4
+ data.tar.gz: b933d30e9d959fd0ef51958f5815349cab06f8dc7069b4f10c16907e43be53a5
5
5
  SHA512:
6
- metadata.gz: 57b94e3a5a06724249509077ada410188ad29b52ae6dfda9d8b56582cc08bdb443a60e75744abf0d2ac664b3124db18e3e5382f72ccacfd4be64faf2c489b0ae
7
- data.tar.gz: fb563b7256b89462268c6b3dc4b5cbf626764d2a3097dc5a332187a78c4f7d9d0c80c6dd2ba83692d48ba354696467329a87acf25474261a24bd9bffcd42f35a
6
+ metadata.gz: 070a442e799b151ea2be23c3eb0d00ad25cc269ed6296ca3862fb6b3b25bfff238886423e7ae52cea853041038fefa354f818377cfde730b4464d7503b0680da
7
+ data.tar.gz: b14a228097fd48fc7c3dd4c7674b607574f99fba7b9870b64e97b836340181b57563794dd1d5371929fa1dac7e33430eb14189447b05caba84e8ce2b5034f12e
data/README.md CHANGED
@@ -9,6 +9,7 @@
9
9
  [![Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)](https://www.patreon.com/bbatsov)
10
10
  [![OpenCollective](https://opencollective.com/rubocop/backers/badge.svg)](#open-collective-backers)
11
11
  [![OpenCollective](https://opencollective.com/rubocop/sponsors/badge.svg)](#open-collective-sponsors)
12
+ [![Tidelift](https://tidelift.com/badges/package/rubygems/rubocop)](https://tidelift.com/subscription/pkg/rubygems-rubocop?utm_source=rubygems-rubocop&utm_medium=referral&utm_campaign=readme)
12
13
 
13
14
  <p align="center">
14
15
  <img src="https://raw.githubusercontent.com/rubocop-hq/rubocop/master/logo/rubo-logo-horizontal.png" alt="RuboCop Logo"/>
@@ -52,7 +53,7 @@ haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you
52
53
  might want to use a conservative version lock in your `Gemfile`:
53
54
 
54
55
  ```rb
55
- gem 'rubocop', '~> 0.74.0', require: false
56
+ gem 'rubocop', '~> 0.75.0', require: false
56
57
  ```
57
58
 
58
59
  ## Quickstart
@@ -1591,6 +1591,11 @@ Lint/ScriptPermission:
1591
1591
  VersionAdded: '0.49'
1592
1592
  VersionChanged: '0.50'
1593
1593
 
1594
+ Lint/SendWithMixinArgument:
1595
+ Description: 'Checks for `send` method when using mixin.'
1596
+ Enabled: true
1597
+ VersionAdded: '0.75'
1598
+
1594
1599
  Lint/ShadowedArgument:
1595
1600
  Description: 'Avoid reassigning arguments before they were used.'
1596
1601
  Enabled: true
@@ -1746,7 +1751,7 @@ Metrics/AbcSize:
1746
1751
  branches, and conditions.
1747
1752
  Reference:
1748
1753
  - http://c2.com/cgi/wiki?AbcMetric
1749
- - https://en.wikipedia.org/wiki/ABC_Software_Metric'
1754
+ - https://en.wikipedia.org/wiki/ABC_Software_Metric
1750
1755
  Enabled: true
1751
1756
  VersionAdded: '0.27'
1752
1757
  VersionChanged: '0.66'
@@ -1849,6 +1854,14 @@ Metrics/PerceivedComplexity:
1849
1854
  VersionAdded: '0.25'
1850
1855
  Max: 7
1851
1856
 
1857
+ ################## Migration #############################
1858
+
1859
+ Migration/DepartmentName:
1860
+ Description: >-
1861
+ Check that cop names in rubocop:disable (etc) comments are
1862
+ given with department name.
1863
+ Enabled: false
1864
+
1852
1865
  #################### Naming ##############################
1853
1866
 
1854
1867
  Naming/AccessorMethodName:
@@ -1984,6 +1997,13 @@ Naming/MethodName:
1984
1997
  SupportedStyles:
1985
1998
  - snake_case
1986
1999
  - camelCase
2000
+ # Method names matching patterns are always allowed.
2001
+ #
2002
+ # IgnoredPatterns:
2003
+ # - '\A\s*onSelectionBulkChange\s*'
2004
+ # - '\A\s*onSelectionCleared\s*'
2005
+ #
2006
+ IgnoredPatterns: []
1987
2007
 
1988
2008
  Naming/PredicateName:
1989
2009
  Description: 'Check the names of predicate methods.'
@@ -2706,7 +2726,7 @@ Style/FormatStringToken:
2706
2726
  - template
2707
2727
  - unannotated
2708
2728
  VersionAdded: '0.49'
2709
- VersionChanged: '0.52'
2729
+ VersionChanged: '0.75'
2710
2730
 
2711
2731
  Style/FrozenStringLiteralComment:
2712
2732
  Description: >-
@@ -2899,6 +2919,7 @@ Style/MethodCallWithArgsParentheses:
2899
2919
  VersionChanged: '0.61'
2900
2920
  IgnoreMacros: true
2901
2921
  IgnoredMethods: []
2922
+ IgnoredPatterns: []
2902
2923
  IncludedMacros: []
2903
2924
  AllowParenthesesInMultilineCall: false
2904
2925
  AllowParenthesesInChaining: false
@@ -3586,6 +3607,8 @@ Style/StringHashKeys:
3586
3607
  StyleGuide: '#symbols-as-keys'
3587
3608
  Enabled: false
3588
3609
  VersionAdded: '0.52'
3610
+ VersionChanged: '0.75'
3611
+ Safe: false
3589
3612
 
3590
3613
  Style/StringLiterals:
3591
3614
  Description: 'Checks if uses of quotes match the configured preference.'
@@ -3904,8 +3927,9 @@ Style/YodaCondition:
3904
3927
  - require_for_all_comparison_operators
3905
3928
  # enforce yoda only for equality operators: `!=` and `==`
3906
3929
  - require_for_equality_operators_only
3930
+ Safe: false
3907
3931
  VersionAdded: '0.49'
3908
- VersionChanged: '0.63'
3932
+ VersionChanged: '0.75'
3909
3933
 
3910
3934
  Style/ZeroLengthPredicate:
3911
3935
  Description: 'Use #empty? when testing for objects of length 0.'
@@ -120,7 +120,6 @@ require_relative 'rubocop/cop/mixin/frozen_string_literal'
120
120
  require_relative 'rubocop/cop/mixin/hash_alignment'
121
121
  require_relative 'rubocop/cop/mixin/ignored_pattern'
122
122
  require_relative 'rubocop/cop/mixin/ignored_methods'
123
- require_relative 'rubocop/cop/mixin/ignored_method_patterns'
124
123
  require_relative 'rubocop/cop/mixin/integer_node'
125
124
  require_relative 'rubocop/cop/mixin/interpolation'
126
125
  require_relative 'rubocop/cop/mixin/match_range'
@@ -158,6 +157,10 @@ require_relative 'rubocop/cop/mixin/trailing_comma'
158
157
  require_relative 'rubocop/cop/mixin/uncommunicative_name'
159
158
  require_relative 'rubocop/cop/mixin/unused_argument'
160
159
 
160
+ require_relative 'rubocop/cop/utils/format_string'
161
+
162
+ require_relative 'rubocop/cop/migration/department_name'
163
+
161
164
  require_relative 'rubocop/cop/correctors/alignment_corrector'
162
165
  require_relative 'rubocop/cop/correctors/condition_corrector'
163
166
  require_relative 'rubocop/cop/correctors/each_to_for_corrector'
@@ -329,6 +332,7 @@ require_relative 'rubocop/cop/lint/safe_navigation_consistency'
329
332
  require_relative 'rubocop/cop/lint/safe_navigation_chain'
330
333
  require_relative 'rubocop/cop/lint/safe_navigation_with_empty'
331
334
  require_relative 'rubocop/cop/lint/script_permission'
335
+ require_relative 'rubocop/cop/lint/send_with_mixin_argument'
332
336
  require_relative 'rubocop/cop/lint/shadowed_argument'
333
337
  require_relative 'rubocop/cop/lint/shadowed_exception'
334
338
  require_relative 'rubocop/cop/lint/shadowing_outer_local_variable'
@@ -578,6 +582,7 @@ require_relative 'rubocop/formatter/progress_formatter'
578
582
  require_relative 'rubocop/formatter/quiet_formatter'
579
583
  require_relative 'rubocop/formatter/tap_formatter'
580
584
  require_relative 'rubocop/formatter/worst_offenders_formatter'
585
+ require_relative 'rubocop/formatter/pacman_formatter'
581
586
  # relies on progress formatter
582
587
  require_relative 'rubocop/formatter/auto_gen_config_formatter'
583
588
 
@@ -222,22 +222,11 @@ module RuboCop
222
222
 
223
223
  def_node_matcher :macro_scope?, <<~PATTERN
224
224
  {^{({sclass class module block} ...) class_constructor?}
225
- ^^#ascend_macro_scope?
225
+ ^^{({sclass class module block} ... ({begin if} ...)) class_constructor?}
226
226
  ^#macro_kwbegin_wrapper?
227
227
  #root_node?}
228
228
  PATTERN
229
229
 
230
- def_node_matcher :wrapped_macro_scope?, <<~PATTERN
231
- {({sclass class module block} ... ({begin if} ...)) class_constructor?}
232
- PATTERN
233
-
234
- def ascend_macro_scope?(ancestor)
235
- return true if wrapped_macro_scope?(ancestor)
236
- return false if root_node?(ancestor)
237
-
238
- ascend_macro_scope?(ancestor.parent)
239
- end
240
-
241
230
  # Check if a node's parent is a kwbegin wrapper within a macro scope
242
231
  #
243
232
  # @param parent [Node] parent of the node being checked
@@ -11,7 +11,8 @@ module RuboCop
11
11
  COPS_PATTERN = "(all|#{COP_NAMES_PATTERN})"
12
12
 
13
13
  COMMENT_DIRECTIVE_REGEXP = Regexp.new(
14
- ('# rubocop : ((?:dis|en)able)\b ' + COPS_PATTERN).gsub(' ', '\s*')
14
+ ('# rubocop : ((?:disable|enable|todo))\b ' + COPS_PATTERN)
15
+ .gsub(' ', '\s*')
15
16
  )
16
17
 
17
18
  CopAnalysis = Struct.new(:line_ranges, :start_line_number)
@@ -141,7 +142,7 @@ module RuboCop
141
142
  cop_names =
142
143
  cops_string == 'all' ? all_cop_names : cops_string.split(/,\s*/)
143
144
 
144
- disabled = (switch == 'disable')
145
+ disabled = %w[disable todo].include?(switch)
145
146
 
146
147
  [cop_names, disabled]
147
148
  end
@@ -96,6 +96,10 @@ module RuboCop
96
96
  @for_cop[cop.respond_to?(:cop_name) ? cop.cop_name : cop]
97
97
  end
98
98
 
99
+ def for_department(department_name)
100
+ @for_cop[department_name]
101
+ end
102
+
99
103
  def for_all_cops
100
104
  @for_all_cops ||= self['AllCops'] || {}
101
105
  end
@@ -199,6 +199,8 @@ module RuboCop
199
199
  raise(TypeError, "Malformed configuration in #{absolute_path}")
200
200
  end
201
201
 
202
+ check_cop_config_value(hash)
203
+
202
204
  hash
203
205
  end
204
206
 
@@ -220,6 +222,22 @@ module RuboCop
220
222
  end
221
223
  end
222
224
 
225
+ def check_cop_config_value(hash, parent = nil)
226
+ hash.each do |key, value|
227
+ check_cop_config_value(value, key) if value.is_a?(Hash)
228
+
229
+ next unless %w[Enabled
230
+ Safe
231
+ SafeAutoCorrect
232
+ AutoCorrect].include?(key) && value.is_a?(String)
233
+
234
+ abort(
235
+ "Property #{Rainbow(key).yellow} of cop #{Rainbow(parent).yellow}" \
236
+ " is supposed to be a boolean and #{Rainbow(value).yellow} is not."
237
+ )
238
+ end
239
+ end
240
+
223
241
  # Read the specified file, or exit with a friendly, concise message on
224
242
  # stderr. Care is taken to use the standard OS exit code for a "file not
225
243
  # found" error.
@@ -240,11 +258,11 @@ module RuboCop
240
258
  yaml_code,
241
259
  permitted_classes: [Regexp, Symbol],
242
260
  permitted_symbols: [],
243
- aliases: false,
261
+ aliases: true,
244
262
  filename: filename
245
263
  )
246
264
  else
247
- YAML.safe_load(yaml_code, [Regexp, Symbol], [], false, filename)
265
+ YAML.safe_load(yaml_code, [Regexp, Symbol], [], true, filename)
248
266
  end
249
267
  end
250
268
  end
@@ -73,7 +73,7 @@ module RuboCop
73
73
 
74
74
  opts = { inherit_mode: config['inherit_mode'] || {},
75
75
  unset_nil: unset_nil }
76
- Config.new(merge(default_configuration, config, opts), config_file)
76
+ Config.new(merge(default_configuration, config, **opts), config_file)
77
77
  end
78
78
 
79
79
  # Return a recursive merge of two hashes. That is, a normal hash merge,
@@ -92,7 +92,7 @@ module RuboCop
92
92
  elsif should_union?(base_hash, key, opts[:inherit_mode])
93
93
  result[key] = base_hash[key] | derived_hash[key]
94
94
  elsif opts[:debug]
95
- warn_on_duplicate_setting(base_hash, derived_hash, key, opts)
95
+ warn_on_duplicate_setting(base_hash, derived_hash, key, **opts)
96
96
  end
97
97
  end
98
98
  result
@@ -119,6 +119,18 @@ module RuboCop
119
119
  cops: 'Rails/UniqBeforePluck',
120
120
  parameters: 'EnforcedMode',
121
121
  alternative: '`EnforcedMode` has been renamed to `EnforcedStyle`'
122
+ },
123
+ {
124
+ cops: 'Style/MethodCallWithArgsParentheses',
125
+ parameters: 'IgnoredMethodPatterns',
126
+ alternative: '`IgnoredMethodPatterns` has been renamed to ' \
127
+ '`IgnoredPatterns`'
128
+ },
129
+ {
130
+ cops: %w[Performance/Count Performance/Detect],
131
+ parameters: 'SafeMode',
132
+ alternative: '`SafeMode` has been removed. ' \
133
+ 'Use `SafeAutoCorrect` instead.'
122
134
  }
123
135
  ].freeze
124
136
 
@@ -39,7 +39,7 @@ module RuboCop
39
39
 
40
40
  def disable_offense(node)
41
41
  range = node.location.expression
42
- eol_comment = " # rubocop:disable #{cop_name}"
42
+ eol_comment = " # rubocop:todo #{cop_name}"
43
43
  needed_line_length = range.column +
44
44
  (range.source_line + eol_comment).length
45
45
  if needed_line_length <= max_line_length
@@ -90,7 +90,7 @@ module RuboCop
90
90
 
91
91
  corrector.insert_before(
92
92
  range_with_newline,
93
- "#{leading_whitespace}# rubocop:disable #{cop_name}\n"
93
+ "#{leading_whitespace}# rubocop:todo #{cop_name}\n"
94
94
  )
95
95
  corrector.insert_after(
96
96
  range_with_newline,
@@ -160,10 +160,11 @@ module RuboCop
160
160
  return :uncorrected unless correction
161
161
 
162
162
  @corrections << Correction.new(correction, node, self)
163
+ :corrected
163
164
  elsif disable_uncorrectable?
164
165
  disable_uncorrectable(node)
166
+ :corrected_with_todo
165
167
  end
166
- :corrected
167
168
  end
168
169
 
169
170
  def reason_to_not_correct(node)
@@ -224,8 +225,8 @@ module RuboCop
224
225
 
225
226
  def annotate(message)
226
227
  RuboCop::Cop::MessageAnnotator.new(
227
- config, cop_config, @options
228
- ).annotate(message, name)
228
+ config, cop_name, cop_config, @options
229
+ ).annotate(message)
229
230
  end
230
231
 
231
232
  def file_name_matches_any?(file, parameter, default_result)
@@ -19,10 +19,12 @@ module RuboCop
19
19
  expr = node.respond_to?(:loc) ? node.loc.expression : node
20
20
  return if block_comment_within?(expr)
21
21
 
22
+ taboo_ranges = inside_string_ranges(node)
23
+
22
24
  lambda do |corrector|
23
25
  each_line(expr) do |line_begin_pos|
24
26
  autocorrect_line(corrector, line_begin_pos, expr, column_delta,
25
- heredoc_ranges(node))
27
+ taboo_ranges)
26
28
  end
27
29
  end
28
30
  end
@@ -39,27 +41,48 @@ module RuboCop
39
41
  private
40
42
 
41
43
  def autocorrect_line(corrector, line_begin_pos, expr, column_delta,
42
- heredoc_ranges)
44
+ taboo_ranges)
43
45
  range = calculate_range(expr, line_begin_pos, column_delta)
44
- # We must not change indentation of heredoc strings.
45
- return if heredoc_ranges.any? { |h| within?(range, h) }
46
+ # We must not change indentation of heredoc strings or inside other
47
+ # string literals
48
+ return if taboo_ranges.any? { |t| within?(range, t) }
46
49
 
47
50
  if column_delta.positive?
48
- unless range.source == "\n"
49
- # TODO: Fix ranges instead of using `begin`
50
- corrector.insert_before(range.begin, ' ' * column_delta)
51
+ unless range.resize(1).source == "\n"
52
+ corrector.insert_before(range, ' ' * column_delta)
51
53
  end
52
54
  elsif range.source =~ /\A[ \t]+\z/
53
55
  remove(range, corrector)
54
56
  end
55
57
  end
56
58
 
57
- def heredoc_ranges(node)
59
+ def inside_string_ranges(node)
58
60
  return [] unless node.is_a?(Parser::AST::Node)
59
61
 
60
- node.each_node(:dstr)
61
- .select(&:heredoc?)
62
- .map { |n| n.loc.heredoc_body.join(n.loc.heredoc_end) }
62
+ node.each_node(:str, :dstr, :xstr).map { |n| inside_string_range(n) }
63
+ .compact
64
+ end
65
+
66
+ def inside_string_range(node)
67
+ loc = node.location
68
+
69
+ if node.heredoc?
70
+ loc.heredoc_body.join(loc.heredoc_end)
71
+ elsif delimited_string_literal?(node)
72
+ loc.begin.end.join(loc.end.begin)
73
+ end
74
+ end
75
+
76
+ # Some special kinds of string literals are not composed of literal
77
+ # characters between two delimiters:
78
+ # - The source map of `?a` responds to :begin and :end but its end is
79
+ # nil.
80
+ # - The source map of `__FILE__` responds to neither :begin nor :end.
81
+ def delimited_string_literal?(node)
82
+ loc = node.location
83
+
84
+ loc.respond_to?(:begin) && loc.begin &&
85
+ loc.respond_to?(:end) && loc.end
63
86
  end
64
87
 
65
88
  def block_comment_within?(expr)
@@ -69,15 +92,18 @@ module RuboCop
69
92
  end
70
93
 
71
94
  def calculate_range(expr, line_begin_pos, column_delta)
95
+ if column_delta.positive?
96
+ return range_between(line_begin_pos, line_begin_pos)
97
+ end
98
+
72
99
  starts_with_space =
73
100
  expr.source_buffer.source[line_begin_pos].start_with?(' ')
74
- pos_to_remove = if column_delta.positive? || starts_with_space
75
- line_begin_pos
76
- else
77
- line_begin_pos - column_delta.abs
78
- end
79
101
 
80
- range_between(pos_to_remove, pos_to_remove + column_delta.abs)
102
+ if starts_with_space
103
+ range_between(line_begin_pos, line_begin_pos + column_delta.abs)
104
+ else
105
+ range_between(line_begin_pos - column_delta.abs, line_begin_pos)
106
+ end
81
107
  end
82
108
 
83
109
  def remove(range, corrector)
@@ -40,8 +40,8 @@ module RuboCop
40
40
  range_with_surrounding_space(range: node.loc.end, side: :left)
41
41
  )
42
42
 
43
- corrector.insert_after(
44
- last_element_range_with_trailing_comma(node),
43
+ corrector.insert_before(
44
+ last_element_range_with_trailing_comma(node).end,
45
45
  node.loc.end.source
46
46
  )
47
47
  end
@@ -10,10 +10,10 @@ module RuboCop
10
10
  # Note: RDoc 5.1.0 or lower has the following issue.
11
11
  # https://github.com/rubocop-hq/rubocop/issues/7043
12
12
  #
13
- # The following `String#strip_indent` can be replaced with
13
+ # The following `String#gsub` can be replaced with
14
14
  # squiggly heredoc when RuboCop supports Ruby 2.5 or higher
15
15
  # (RDoc 6.0 or higher).
16
- SOURCE_TEMPLATE = <<-RUBY.strip_indent
16
+ SOURCE_TEMPLATE = <<-RUBY.gsub(/^ {8}/, '')
17
17
  # frozen_string_literal: true
18
18
 
19
19
  # TODO: when finished, run `rake generate_cops_documentation` to update the docs
@@ -61,7 +61,7 @@ module RuboCop
61
61
  # See https://github.com/rubocop-hq/rubocop/blob/master/lib/rubocop/node_pattern.rb
62
62
  #
63
63
  # For example
64
- MSG = 'Use `#good_method` instead of `#bad_method`.'.freeze
64
+ MSG = 'Use `#good_method` instead of `#bad_method`.'
65
65
 
66
66
  def_node_matcher :bad_method?, <<~PATTERN
67
67
  (send nil? :bad_method ...)