rubocop 1.21.0 → 1.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +43 -6
  4. data/lib/rubocop/config.rb +5 -0
  5. data/lib/rubocop/config_loader.rb +2 -0
  6. data/lib/rubocop/config_validator.rb +9 -1
  7. data/lib/rubocop/cop/base.rb +1 -1
  8. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +34 -11
  9. data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
  10. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
  11. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
  12. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +1 -1
  13. data/lib/rubocop/cop/generator.rb +14 -8
  14. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  15. data/lib/rubocop/cop/layout/dot_position.rb +25 -2
  16. data/lib/rubocop/cop/layout/line_length.rb +7 -5
  17. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
  18. data/lib/rubocop/cop/layout/space_inside_parens.rb +74 -24
  19. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +5 -1
  20. data/lib/rubocop/cop/lint/ambiguous_range.rb +7 -7
  21. data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
  22. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
  23. data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
  24. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
  25. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
  26. data/lib/rubocop/cop/lint/else_layout.rb +9 -5
  27. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
  28. data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
  29. data/lib/rubocop/cop/lint/loop.rb +4 -3
  30. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
  31. data/lib/rubocop/cop/lint/number_conversion.rb +5 -0
  32. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  33. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
  34. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
  35. data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
  36. data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
  37. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
  38. data/lib/rubocop/cop/lint/require_relative_self_path.rb +49 -0
  39. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
  40. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  41. data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
  42. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
  43. data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
  44. data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
  45. data/lib/rubocop/cop/lint/useless_times.rb +3 -2
  46. data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
  47. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +5 -1
  48. data/lib/rubocop/cop/mixin/heredoc.rb +1 -3
  49. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
  50. data/lib/rubocop/cop/mixin/percent_array.rb +6 -1
  51. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  52. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
  53. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
  54. data/lib/rubocop/cop/security/io_methods.rb +49 -0
  55. data/lib/rubocop/cop/security/json_load.rb +8 -7
  56. data/lib/rubocop/cop/security/open.rb +4 -0
  57. data/lib/rubocop/cop/security/yaml_load.rb +4 -0
  58. data/lib/rubocop/cop/style/and_or.rb +4 -3
  59. data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
  60. data/lib/rubocop/cop/style/array_coercion.rb +21 -3
  61. data/lib/rubocop/cop/style/case_like_if.rb +5 -0
  62. data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
  63. data/lib/rubocop/cop/style/collection_compact.rb +7 -5
  64. data/lib/rubocop/cop/style/collection_methods.rb +6 -5
  65. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  66. data/lib/rubocop/cop/style/commented_keyword.rb +4 -1
  67. data/lib/rubocop/cop/style/date_time.rb +5 -0
  68. data/lib/rubocop/cop/style/double_negation.rb +15 -5
  69. data/lib/rubocop/cop/style/float_division.rb +10 -2
  70. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +6 -1
  71. data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
  72. data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
  73. data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -6
  74. data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
  75. data/lib/rubocop/cop/style/identical_conditional_branches.rb +18 -16
  76. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +15 -2
  77. data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
  78. data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
  79. data/lib/rubocop/cop/style/line_end_concatenation.rb +13 -0
  80. data/lib/rubocop/cop/style/module_function.rb +8 -9
  81. data/lib/rubocop/cop/style/mutable_constant.rb +12 -7
  82. data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
  83. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
  84. data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
  85. data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
  86. data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
  87. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
  88. data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
  89. data/lib/rubocop/cop/style/redundant_argument.rb +14 -7
  90. data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
  91. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
  92. data/lib/rubocop/cop/style/redundant_freeze.rb +0 -1
  93. data/lib/rubocop/cop/style/redundant_self.rb +10 -0
  94. data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
  95. data/lib/rubocop/cop/style/redundant_sort.rb +47 -29
  96. data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
  97. data/lib/rubocop/cop/style/select_by_regexp.rb +106 -0
  98. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
  99. data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
  100. data/lib/rubocop/cop/style/special_global_vars.rb +4 -0
  101. data/lib/rubocop/cop/style/static_class.rb +4 -3
  102. data/lib/rubocop/cop/style/string_chars.rb +4 -2
  103. data/lib/rubocop/cop/style/string_concatenation.rb +4 -0
  104. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
  105. data/lib/rubocop/cop/style/struct_inheritance.rb +3 -2
  106. data/lib/rubocop/cop/style/swap_values.rb +4 -2
  107. data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
  108. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
  109. data/lib/rubocop/cop/style/yoda_condition.rb +20 -0
  110. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
  111. data/lib/rubocop/cop/util.rb +2 -2
  112. data/lib/rubocop/cops_documentation_generator.rb +17 -5
  113. data/lib/rubocop/options.rb +126 -112
  114. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  115. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  116. data/lib/rubocop/version.rb +1 -1
  117. data/lib/rubocop.rb +5 -0
  118. metadata +10 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd3bb4ebea9d6db387e52e92a0c9ffac3f6215f0b5b9bcd7d555e979c8fb9fa7
4
- data.tar.gz: 208d08bf57f092a0857776924cb529db1324ecdf4696476475f51878f803b6ac
3
+ metadata.gz: '08520f6dcf324dcb95ce7191673f070e86c3b5c2613942d19e4c951119a43476'
4
+ data.tar.gz: 90fd28bb4692e3feb9973d0b711a181c90608b205741b4b68cc23df9a9d42142
5
5
  SHA512:
6
- metadata.gz: 9d32668f49f495948628017c042cbc292d62c4ba93d905635d47ecba7c12e69ff7cbff3999a6cccba62bbc27ff7b51827e1a00f41769c1dd711f342fe10e8519
7
- data.tar.gz: 9798e105b8ea95245d153e9e295a95a593e49464f91ac8c508ce0900f7f2ef0e97759a1144044f32acb726e11d3552de1f5de8d2d477151606bfd39090df3260
6
+ metadata.gz: 27a14f94b096be10618d7670ff591f4443ab4e09d8fce7f2604e686a1f7ab5544aaf53136c09a6ec62198f9f56950b5ab0c3cea64ee0ccd565e328b7ba131a5d
7
+ data.tar.gz: 419cf3d94cf235cf31b09d26cbed550937dcb1930797e3e28c97cfb27116b160732aeec5434de8e0c3417f6900bf795c1826d7941e49cf8f12e9a15c245472b4
data/README.md CHANGED
@@ -54,7 +54,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
54
54
  in your `Gemfile`:
55
55
 
56
56
  ```rb
57
- gem 'rubocop', '~> 1.21', require: false
57
+ gem 'rubocop', '~> 1.22', require: false
58
58
  ```
59
59
 
60
60
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -130,7 +130,7 @@ AllCops:
130
130
  # What MRI version of the Ruby interpreter is the inspected code intended to
131
131
  # run on? (If there is more than one, set this to the lowest version.)
132
132
  # If a value is specified for TargetRubyVersion then it is used. Acceptable
133
- # values are specificed as a float (i.e. 3.0); the teeny version of Ruby
133
+ # values are specified as a float (i.e. 3.0); the teeny version of Ruby
134
134
  # should not be included. If the project specifies a Ruby version in the
135
135
  # .tool-versions or .ruby-version files, Gemfile or gems.rb file, RuboCop will
136
136
  # try to determine the desired version of Ruby by inspecting the
@@ -209,6 +209,7 @@ Bundler/InsecureProtocolSource:
209
209
  'https://rubygems.org' if possible, or 'http://rubygems.org' if not.
210
210
  Enabled: true
211
211
  VersionAdded: '0.50'
212
+ AllowHttpProtocol: true
212
213
  Include:
213
214
  - '**/*.gemfile'
214
215
  - '**/Gemfile'
@@ -1360,10 +1361,11 @@ Layout/SpaceInsideParens:
1360
1361
  StyleGuide: '#spaces-braces'
1361
1362
  Enabled: true
1362
1363
  VersionAdded: '0.49'
1363
- VersionChanged: '0.55'
1364
+ VersionChanged: '1.22'
1364
1365
  EnforcedStyle: no_space
1365
1366
  SupportedStyles:
1366
1367
  - space
1368
+ - compact
1367
1369
  - no_space
1368
1370
 
1369
1371
  Layout/SpaceInsidePercentLiteralDelimiters:
@@ -1491,9 +1493,9 @@ Lint/BinaryOperatorWithIdenticalOperands:
1491
1493
  Lint/BooleanSymbol:
1492
1494
  Description: 'Check for `:true` and `:false` symbols.'
1493
1495
  Enabled: true
1494
- Safe: false
1496
+ SafeAutoCorrect: false
1495
1497
  VersionAdded: '0.50'
1496
- VersionChanged: '0.83'
1498
+ VersionChanged: '1.22'
1497
1499
 
1498
1500
  Lint/CircularArgumentReference:
1499
1501
  Description: "Default values in optional keyword arguments and optional ordinal arguments should not refer back to the name of the argument."
@@ -2045,6 +2047,11 @@ Lint/RequireParentheses:
2045
2047
  Enabled: true
2046
2048
  VersionAdded: '0.18'
2047
2049
 
2050
+ Lint/RequireRelativeSelfPath:
2051
+ Description: 'Checks for uses a file requiring itself with `require_relative`.'
2052
+ Enabled: pending
2053
+ VersionAdded: '1.22'
2054
+
2048
2055
  Lint/RescueException:
2049
2056
  Description: 'Avoid rescuing the Exception class.'
2050
2057
  StyleGuide: '#no-blind-rescues'
@@ -2732,6 +2739,14 @@ Security/Eval:
2732
2739
  Enabled: true
2733
2740
  VersionAdded: '0.47'
2734
2741
 
2742
+ Security/IoMethods:
2743
+ Description: >-
2744
+ Checks for the first argument to `IO.read`, `IO.binread`, `IO.write`, `IO.binwrite`,
2745
+ `IO.foreach`, and `IO.readlines`.
2746
+ Enabled: pending
2747
+ Safe: false
2748
+ VersionAdded: '1.22'
2749
+
2735
2750
  Security/JSONLoad:
2736
2751
  Description: >-
2737
2752
  Prefer usage of `JSON.parse` over `JSON.load` due to potential
@@ -3703,7 +3718,7 @@ Style/InPatternThen:
3703
3718
  Style/InfiniteLoop:
3704
3719
  Description: >-
3705
3720
  Use Kernel#loop for infinite loops.
3706
- This cop is unsafe in the body may raise a `StopIteration` exception.
3721
+ This cop is unsafe if the body may raise a `StopIteration` exception.
3707
3722
  Safe: false
3708
3723
  StyleGuide: '#infinite-loop'
3709
3724
  Enabled: true
@@ -4129,6 +4144,21 @@ Style/Not:
4129
4144
  VersionAdded: '0.9'
4130
4145
  VersionChanged: '0.20'
4131
4146
 
4147
+ Style/NumberedParameters:
4148
+ Description: 'Restrict the usage of numbered parameters.'
4149
+ Enabled: pending
4150
+ VersionAdded: '1.22'
4151
+ EnforcedStyle: allow_single_line
4152
+ SupportedStyles:
4153
+ - allow_single_line
4154
+ - disallow
4155
+
4156
+ Style/NumberedParametersLimit:
4157
+ Description: 'Avoid excessive numbered params in a single block.'
4158
+ Enabled: pending
4159
+ VersionAdded: '1.22'
4160
+ Max: 1
4161
+
4132
4162
  Style/NumericLiteralPrefix:
4133
4163
  Description: 'Use smallcase prefixes for numeric literals.'
4134
4164
  StyleGuide: '#numeric-literal-prefixes'
@@ -4139,7 +4169,6 @@ Style/NumericLiteralPrefix:
4139
4169
  - zero_with_o
4140
4170
  - zero_only
4141
4171
 
4142
-
4143
4172
  Style/NumericLiterals:
4144
4173
  Description: >-
4145
4174
  Add underscores to large numeric literals to improve their
@@ -4460,6 +4489,8 @@ Style/RedundantSort:
4460
4489
  `max_by` instead of `sort_by...last`, etc.
4461
4490
  Enabled: true
4462
4491
  VersionAdded: '0.76'
4492
+ VersionChanged: '1.22'
4493
+ Safe: false
4463
4494
 
4464
4495
  Style/RedundantSortBy:
4465
4496
  Description: 'Use `sort` instead of `sort_by { |x| x }`.'
@@ -4540,6 +4571,12 @@ Style/Sample:
4540
4571
  Enabled: true
4541
4572
  VersionAdded: '0.30'
4542
4573
 
4574
+ Style/SelectByRegexp:
4575
+ Description: 'Prefer grep/grep_v to select/reject with a regexp match.'
4576
+ Enabled: pending
4577
+ SafeAutoCorrect: false
4578
+ VersionAdded: '1.22'
4579
+
4543
4580
  Style/SelfAssignment:
4544
4581
  Description: >-
4545
4582
  Checks for places where self-assignment shorthand should have
@@ -51,6 +51,11 @@ module RuboCop
51
51
  self
52
52
  end
53
53
 
54
+ def validate_after_resolution
55
+ @validator.validate_after_resolution
56
+ self
57
+ end
58
+
54
59
  def_delegators :@hash, :[], :[]=, :delete, :dig, :each, :key?, :keys, :each_key,
55
60
  :fetch, :map, :merge, :replace, :to_h, :to_hash, :transform_values
56
61
  def_delegators :@validator, :validate, :target_ruby_version
@@ -101,6 +101,8 @@ module RuboCop
101
101
  return default_configuration if config_file == DEFAULT_FILE
102
102
 
103
103
  config = load_file(config_file, check: check)
104
+ config.validate_after_resolution if check
105
+
104
106
  if ignore_parent_exclusion?
105
107
  print 'Ignoring AllCops/Exclude from parent folders' if debug?
106
108
  else
@@ -44,7 +44,6 @@ module RuboCop
44
44
  check_obsoletions
45
45
 
46
46
  alert_about_unrecognized_cops(invalid_cop_names)
47
- check_target_ruby
48
47
  validate_new_cops_parameter
49
48
  validate_parameter_names(valid_cop_names)
50
49
  validate_enforced_styles(valid_cop_names)
@@ -52,6 +51,15 @@ module RuboCop
52
51
  reject_mutually_exclusive_defaults
53
52
  end
54
53
 
54
+ # Validations that should only be run after all config resolving has
55
+ # taken place:
56
+ # * The target ruby version is only checked once the entire inheritance
57
+ # chain has been loaded so that only the final value is validated, and
58
+ # any obsolete but overridden values are ignored.
59
+ def validate_after_resolution
60
+ check_target_ruby
61
+ end
62
+
55
63
  def target_ruby_version
56
64
  target_ruby.version
57
65
  end
@@ -24,7 +24,7 @@ module RuboCop
24
24
  # `add_global_offense`. Use the `processed_source` method to
25
25
  # get the currently processed source being investigated.
26
26
  #
27
- # In case of invalid syntax / unparseable content,
27
+ # In case of invalid syntax / unparsable content,
28
28
  # the callback `on_other_file` is called instead of all the other
29
29
  # `on_...` callbacks.
30
30
  #
@@ -16,6 +16,9 @@ module RuboCop
16
16
  # However, you should strongly prefer `https://` where possible, as it is
17
17
  # more secure.
18
18
  #
19
+ # If you don't allow `http://`, please set `false` to `AllowHttpProtocol`.
20
+ # This option is `true` by default for safe autocorrection.
21
+ #
19
22
  # @example
20
23
  # # bad
21
24
  # source :gemcutter
@@ -24,8 +27,17 @@ module RuboCop
24
27
  #
25
28
  # # good
26
29
  # source 'https://rubygems.org' # strongly recommended
30
+ #
31
+ # @example AllowHttpProtocol: true (default)
32
+ #
33
+ # # good
27
34
  # source 'http://rubygems.org' # use only if HTTPS is unavailable
28
35
  #
36
+ # @example AllowHttpProtocol: false
37
+ #
38
+ # # bad
39
+ # source 'http://rubygems.org'
40
+ #
29
41
  class InsecureProtocolSource < Base
30
42
  include RangeHelp
31
43
  extend AutoCorrector
@@ -34,29 +46,40 @@ module RuboCop
34
46
  'are insecure. ' \
35
47
  "Please change your source to 'https://rubygems.org' " \
36
48
  "if possible, or 'http://rubygems.org' if not."
49
+ MSG_HTTP_PROTOCOL = 'Use `https://rubygems.org` instead of `http://rubygems.org`.'
37
50
 
38
51
  RESTRICT_ON_SEND = %i[source].freeze
39
52
 
40
53
  # @!method insecure_protocol_source?(node)
41
54
  def_node_matcher :insecure_protocol_source?, <<~PATTERN
42
55
  (send nil? :source
43
- $(sym ${:gemcutter :rubygems :rubyforge}))
56
+ ${(sym :gemcutter) (sym :rubygems) (sym :rubyforge) (:str "http://rubygems.org")})
44
57
  PATTERN
45
58
 
46
59
  def on_send(node)
47
- insecure_protocol_source?(node) do |source_node, source|
48
- message = format(MSG, source: source)
49
-
50
- add_offense(
51
- source_node,
52
- message: message
53
- ) do |corrector|
54
- corrector.replace(
55
- source_node, "'https://rubygems.org'"
56
- )
60
+ insecure_protocol_source?(node) do |source_node|
61
+ source = source_node.value
62
+ use_http_protocol = source == 'http://rubygems.org'
63
+
64
+ return if allow_http_protocol? && use_http_protocol
65
+
66
+ message = if use_http_protocol
67
+ MSG_HTTP_PROTOCOL
68
+ else
69
+ format(MSG, source: source)
70
+ end
71
+
72
+ add_offense(source_node, message: message) do |corrector|
73
+ corrector.replace(source_node, "'https://rubygems.org'")
57
74
  end
58
75
  end
59
76
  end
77
+
78
+ private
79
+
80
+ def allow_http_protocol?
81
+ cop_config.fetch('AllowHttpProtocol', true)
82
+ end
60
83
  end
61
84
  end
62
85
  end
@@ -24,15 +24,15 @@ module RuboCop
24
24
  # gem 'rubocop'
25
25
  # # For tests
26
26
  # gem 'rspec'
27
- class OrderedGems < Cop # rubocop:disable InternalAffairs/InheritDeprecatedCopClass
28
- include ConfigurableEnforcedStyle
27
+ class OrderedGems < Base
28
+ extend AutoCorrector
29
29
  include OrderedGemNode
30
30
 
31
31
  MSG = 'Gems should be sorted in an alphabetical order within their '\
32
32
  'section of the Gemfile. '\
33
33
  'Gem `%<previous>s` should appear before `%<current>s`.'
34
34
 
35
- def investigate(processed_source)
35
+ def on_new_investigation
36
36
  return if processed_source.blank?
37
37
 
38
38
  gem_declarations(processed_source.ast)
@@ -44,15 +44,6 @@ module RuboCop
44
44
  end
45
45
  end
46
46
 
47
- def autocorrect(node)
48
- OrderedGemCorrector.correct(
49
- processed_source,
50
- node,
51
- previous_declaration(node),
52
- treat_comments_as_separators
53
- )
54
- end
55
-
56
47
  private
57
48
 
58
49
  def previous_declaration(node)
@@ -4,9 +4,10 @@ module RuboCop
4
4
  module Cop
5
5
  # This auto-corrects gem dependency order
6
6
  class OrderedGemCorrector
7
- extend OrderedGemNode
8
-
9
7
  class << self
8
+ include OrderedGemNode
9
+ include RangeHelp
10
+
10
11
  attr_reader :processed_source, :comments_as_separators
11
12
 
12
13
  def correct(processed_source, node,
@@ -17,24 +18,24 @@ module RuboCop
17
18
  current_range = declaration_with_comment(node)
18
19
  previous_range = declaration_with_comment(previous_declaration)
19
20
 
20
- ->(corrector) do swap_range(corrector, current_range, previous_range) end
21
+ ->(corrector) { swap_range(corrector, current_range, previous_range) }
21
22
  end
22
23
 
23
24
  private
24
25
 
25
26
  def declaration_with_comment(node)
26
27
  buffer = processed_source.buffer
27
- begin_pos = get_source_range(node, comments_as_separators).begin_pos
28
+ begin_pos = range_by_whole_lines(get_source_range(node, comments_as_separators)).begin_pos
28
29
  end_line = buffer.line_for_position(node.loc.expression.end_pos)
29
- end_pos = buffer.line_range(end_line).end_pos
30
- Parser::Source::Range.new(buffer, begin_pos, end_pos)
30
+ end_pos = range_by_whole_lines(buffer.line_range(end_line),
31
+ include_final_newline: true).end_pos
32
+
33
+ range_between(begin_pos, end_pos)
31
34
  end
32
35
 
33
36
  def swap_range(corrector, range1, range2)
34
- src1 = range1.source
35
- src2 = range2.source
36
- corrector.replace(range1, src2)
37
- corrector.replace(range2, src1)
37
+ corrector.insert_before(range2, range1.source)
38
+ corrector.remove(range1)
38
39
  end
39
40
  end
40
41
  end
@@ -50,15 +50,15 @@ module RuboCop
50
50
  # spec.add_dependency 'rubocop'
51
51
  # # For tests
52
52
  # spec.add_dependency 'rspec'
53
- class OrderedDependencies < Cop # rubocop:disable InternalAffairs/InheritDeprecatedCopClass
54
- include ConfigurableEnforcedStyle
53
+ class OrderedDependencies < Base
54
+ extend AutoCorrector
55
55
  include OrderedGemNode
56
56
 
57
57
  MSG = 'Dependencies should be sorted in an alphabetical order within ' \
58
58
  'their section of the gemspec. '\
59
59
  'Dependency `%<previous>s` should appear before `%<current>s`.'
60
60
 
61
- def investigate(processed_source)
61
+ def on_new_investigation
62
62
  return if processed_source.blank?
63
63
 
64
64
  dependency_declarations(processed_source.ast)
@@ -71,15 +71,6 @@ module RuboCop
71
71
  end
72
72
  end
73
73
 
74
- def autocorrect(node)
75
- OrderedGemCorrector.correct(
76
- processed_source,
77
- node,
78
- previous_declaration(node),
79
- treat_comments_as_separators
80
- )
81
- end
82
-
83
74
  private
84
75
 
85
76
  def previous_declaration(node)
@@ -42,7 +42,7 @@ module RuboCop
42
42
  # end
43
43
  #
44
44
  # # accepted but not recommended, since
45
- # # Ruby does not really follow semantic versionning
45
+ # # Ruby does not really follow semantic versioning
46
46
  # Gem::Specification.new do |spec|
47
47
  # spec.required_ruby_version = '~> 2.5'
48
48
  # end
@@ -24,6 +24,11 @@ module RuboCop
24
24
  # `SupportedStyle` and unique configuration, there needs to be examples.
25
25
  # Examples must have valid Ruby syntax. Do not use upticks.
26
26
  #
27
+ # @safety
28
+ # Delete this section if the cop is not unsafe (`Safe: false` or
29
+ # `SafeAutoCorrect: false`), or use it to explain how the cop is
30
+ # unsafe.
31
+ #
27
32
  # @example EnforcedStyle: bar (default)
28
33
  # # Description of the `bar` style.
29
34
  #
@@ -106,9 +111,8 @@ module RuboCop
106
111
  '[modify] A configuration for the cop is added into ' \
107
112
  '%<configuration_file_path>s.'
108
113
 
109
- def initialize(name, github_user, output: $stdout)
114
+ def initialize(name, output: $stdout)
110
115
  @badge = Badge.parse(name)
111
- @github_user = github_user
112
116
  @output = output
113
117
  return if badge.qualified?
114
118
 
@@ -142,17 +146,19 @@ module RuboCop
142
146
 
143
147
  def todo
144
148
  <<~TODO
145
- Do 3 steps:
146
- 1. Add an entry to the "New features" section in CHANGELOG.md,
147
- e.g. "Add new `#{badge}` cop. ([@#{github_user}][])"
148
- 2. Modify the description of #{badge} in config/default.yml
149
- 3. Implement your new cop in the generated file!
149
+ Do 4 steps:
150
+ 1. Modify the description of #{badge} in config/default.yml
151
+ 2. Implement your new cop in the generated file!
152
+ 3. Commit your new cop with a message such as
153
+ e.g. "Add new `#{badge}` cop."
154
+ 4. Run `bundle exec rake changelog:new` to generate a changelog entry
155
+ for your new cop.
150
156
  TODO
151
157
  end
152
158
 
153
159
  private
154
160
 
155
- attr_reader :badge, :github_user, :output
161
+ attr_reader :badge, :output
156
162
 
157
163
  def write_unless_file_exists(path, contents)
158
164
  if File.exist?(path)
@@ -23,7 +23,7 @@ module RuboCop
23
23
  extend AutoCorrector
24
24
  include RangeHelp
25
25
 
26
- MSG = 'Preceed `%<method>s` with a `@!method` YARD directive.'
26
+ MSG = 'Precede `%<method>s` with a `@!method` YARD directive.'
27
27
  MSG_WRONG_NAME = '`@!method` YARD directive has invalid method name, ' \
28
28
  'use `%<expected>s` instead of `%<actual>s`.'
29
29
  MSG_TOO_MANY = 'Multiple `@!method` YARD directives found for this matcher.'
@@ -68,7 +68,7 @@ module RuboCop
68
68
  end
69
69
 
70
70
  def proper_dot_position?(node)
71
- receiver_line = node.receiver.source_range.end.line
71
+ receiver_line = receiver_end_line(node.receiver)
72
72
  selector_line = selector_range(node).line
73
73
 
74
74
  # receiver and selector are on the same line
@@ -80,7 +80,10 @@ module RuboCop
80
80
  # dot and the selector otherwise, we might break the code while
81
81
  # "correcting" it (even if there is just an extra blank line, treat
82
82
  # it the same)
83
- return true if line_between?(selector_line, dot_line)
83
+ # Also, in the case of a heredoc, the receiver will end after the dot,
84
+ # because the heredoc body is on subsequent lines, so use the highest
85
+ # line to compare to.
86
+ return true if line_between?(selector_line, [receiver_line, dot_line].max)
84
87
 
85
88
  correct_dot_position_style?(dot_line, selector_line)
86
89
  end
@@ -96,6 +99,26 @@ module RuboCop
96
99
  end
97
100
  end
98
101
 
102
+ def receiver_end_line(node)
103
+ if (line = last_heredoc_line(node))
104
+ line
105
+ else
106
+ node.source_range.end.line
107
+ end
108
+ end
109
+
110
+ def last_heredoc_line(node)
111
+ if node.send_type?
112
+ node.arguments.select { |arg| heredoc?(arg) }.map { |arg| arg.loc.heredoc_end.line }.max
113
+ elsif heredoc?(node)
114
+ node.loc.heredoc_end.line
115
+ end
116
+ end
117
+
118
+ def heredoc?(node)
119
+ (node.str_type? || node.dstr_type?) && node.heredoc?
120
+ end
121
+
99
122
  def selector_range(node)
100
123
  # l.(1) has no selector, so we use the opening parenthesis instead
101
124
  node.loc.selector || node.loc.begin
@@ -183,8 +183,8 @@ module RuboCop
183
183
  line_index.zero? && line.start_with?('#!')
184
184
  end
185
185
 
186
- def register_offense(loc, line, line_index)
187
- message = format(MSG, length: line_length(line), max: max)
186
+ def register_offense(loc, line, line_index, length: line_length(line))
187
+ message = format(MSG, length: length, max: max)
188
188
 
189
189
  self.breakable_range = breakable_range_by_line_index[line_index]
190
190
 
@@ -241,9 +241,10 @@ module RuboCop
241
241
  end
242
242
 
243
243
  def check_directive_line(line, line_index)
244
- return if line_length_without_directive(line) <= max
244
+ length_without_directive = line_length_without_directive(line)
245
+ return if length_without_directive <= max
245
246
 
246
- range = max..(line_length_without_directive(line) - 1)
247
+ range = max..(length_without_directive - 1)
247
248
  register_offense(
248
249
  source_range(
249
250
  processed_source.buffer,
@@ -251,7 +252,8 @@ module RuboCop
251
252
  range
252
253
  ),
253
254
  line,
254
- line_index
255
+ line_index,
256
+ length: length_without_directive
255
257
  )
256
258
  end
257
259
 
@@ -127,6 +127,7 @@ module RuboCop
127
127
  .gsub(/" *\\\n\s*'/, %q(" + ')) # Double quote, backslash, and then single quote
128
128
  .gsub(/' *\\\n\s*"/, %q(' + ")) # Single quote, backslash, and then double quote
129
129
  .gsub(/(["']) *\\\n\s*\1/, '') # Double or single quote, backslash, then same quote
130
+ .gsub(/\n\s*(?=\.\w)/, '') # Extra space within method chaining
130
131
  .gsub(/\s*\\?\n\s*/, ' ') # Any other line break, with or without backslash
131
132
  end
132
133