rubocop 0.87.1 → 0.88.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/bin/rubocop-profile +31 -0
  4. data/config/default.yml +57 -6
  5. data/lib/rubocop.rb +6 -0
  6. data/lib/rubocop/cli.rb +2 -2
  7. data/lib/rubocop/cli/command/auto_genenerate_config.rb +2 -2
  8. data/lib/rubocop/config_loader.rb +20 -7
  9. data/lib/rubocop/config_store.rb +4 -0
  10. data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
  11. data/lib/rubocop/cop/badge.rb +1 -1
  12. data/lib/rubocop/cop/base.rb +12 -4
  13. data/lib/rubocop/cop/cop.rb +1 -1
  14. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +26 -0
  15. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +6 -1
  16. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  17. data/lib/rubocop/cop/layout/end_alignment.rb +3 -2
  18. data/lib/rubocop/cop/layout/multiline_block_layout.rb +16 -5
  19. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +3 -2
  20. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +27 -68
  21. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +3 -2
  22. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +8 -2
  23. data/lib/rubocop/cop/lint/duplicate_elsif_condition.rb +39 -0
  24. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
  25. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +3 -2
  26. data/lib/rubocop/cop/lint/literal_as_condition.rb +11 -1
  27. data/lib/rubocop/cop/lint/nested_method_definition.rb +13 -19
  28. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +67 -0
  29. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -3
  30. data/lib/rubocop/cop/style/accessor_grouping.rb +8 -1
  31. data/lib/rubocop/cop/style/array_coercion.rb +63 -0
  32. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +3 -2
  33. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +5 -4
  34. data/lib/rubocop/cop/style/case_like_if.rb +217 -0
  35. data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
  36. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
  37. data/lib/rubocop/cop/style/exponential_notation.rb +6 -8
  38. data/lib/rubocop/cop/style/float_division.rb +7 -10
  39. data/lib/rubocop/cop/style/format_string_token.rb +5 -5
  40. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +62 -0
  41. data/lib/rubocop/cop/style/hash_like_case.rb +76 -0
  42. data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -11
  43. data/lib/rubocop/cop/style/missing_else.rb +1 -11
  44. data/lib/rubocop/cop/style/numeric_predicate.rb +3 -4
  45. data/lib/rubocop/cop/style/parallel_assignment.rb +3 -3
  46. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  47. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +50 -0
  48. data/lib/rubocop/cop/style/redundant_sort.rb +3 -2
  49. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +3 -2
  50. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +9 -32
  51. data/lib/rubocop/cop/variable_force/variable.rb +5 -3
  52. data/lib/rubocop/file_finder.rb +12 -12
  53. data/lib/rubocop/path_util.rb +2 -17
  54. data/lib/rubocop/result_cache.rb +12 -8
  55. data/lib/rubocop/rspec/expect_offense.rb +31 -5
  56. data/lib/rubocop/rspec/shared_contexts.rb +12 -9
  57. data/lib/rubocop/runner.rb +5 -6
  58. data/lib/rubocop/target_finder.rb +2 -2
  59. data/lib/rubocop/version.rb +1 -1
  60. metadata +9 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 766878b5fd031a287c24a96e8545398cf26adca7b6ea1a3f6b0a3bd15ee07dda
4
- data.tar.gz: 8e33f8a7e7a15ada40bdfbba85c9568e8910c71871af11677f74499241d20c87
3
+ metadata.gz: f95eb2bcf68a27cd9069d1e7cf4fa1b9f4eb499649ccb8c60dcc7327b8bad6b1
4
+ data.tar.gz: 693a6483669b3c11ba0c181b5c1d502c937f34ea73b44710062f9a2a58b34c09
5
5
  SHA512:
6
- metadata.gz: dd87ec99764bc87637c84d50443a60611c87dabb23af42f5339b8911b60898b527e94bed74a1fb925d0ebe91d059041a1214dc7bb53a6d9c4e15a0bafab4c465
7
- data.tar.gz: d747fdfd2254f1b13a332d145aef2fb205afe4aae67c9fddc41d0bdbd6eff13c6f72af18426497ac98ae68a492abcc297892a41e0f2e766ac428029b69e3b9b4
6
+ metadata.gz: a49ca9e1823323f4478552d8217eb924d42e451b909169893e74ce3164c4438a6fce3d2222b1cfc08dc8f88131eae488dee6a98865887e561a8f298a3456dc07
7
+ data.tar.gz: 516d28b2f1d612e9e5a0abfd364ecab6940ef68ec0c2e755b170c43e1961621041b6346478fb59f044494e9d5c9300bfa1307bd580968468586b755b40fc161e
data/README.md CHANGED
@@ -49,7 +49,7 @@ haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you
49
49
  might want to use a conservative version lock in your `Gemfile`:
50
50
 
51
51
  ```rb
52
- gem 'rubocop', '~> 0.87.1', require: false
52
+ gem 'rubocop', '~> 0.88.0', require: false
53
53
  ```
54
54
 
55
55
  ## Quickstart
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ if ARGV.include?('-h') || ARGV.include?('--help')
5
+ puts "Usage: same as main `rubocop` command but gathers profiling info"
6
+ puts "Additional option: `--memory` to print memory usage"
7
+ exit(0)
8
+ end
9
+ with_mem = ARGV.delete('--memory')
10
+
11
+ require 'stackprof'
12
+ if with_mem
13
+ require 'memory_profiler'
14
+ MemoryProfiler.start
15
+ end
16
+ StackProf.start
17
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
18
+ begin
19
+ load "#{__dir__}/../exe/rubocop"
20
+ ensure
21
+ delta = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
22
+ puts "Finished in #{delta.round(1)} seconds"
23
+ StackProf.stop
24
+ if with_mem
25
+ puts "Building memory report..."
26
+ report = MemoryProfiler.stop
27
+ end
28
+ Dir.mkdir('tmp') unless File.exist?('tmp')
29
+ StackProf.results('tmp/stackprof.dump')
30
+ report&.pretty_print(scale_bytes: true)
31
+ end
@@ -1397,12 +1397,18 @@ Lint/DisjunctiveAssignmentInConstructor:
1397
1397
  Enabled: true
1398
1398
  Safe: false
1399
1399
  VersionAdded: '0.62'
1400
+ VersionChanged: '0.88'
1400
1401
 
1401
1402
  Lint/DuplicateCaseCondition:
1402
1403
  Description: 'Do not repeat values in case conditionals.'
1403
1404
  Enabled: true
1404
1405
  VersionAdded: '0.45'
1405
1406
 
1407
+ Lint/DuplicateElsifCondition:
1408
+ Description: 'Do not repeat conditions used in if `elsif`.'
1409
+ Enabled: 'pending'
1410
+ VersionAdded: '0.88'
1411
+
1406
1412
  Lint/DuplicateHashKey:
1407
1413
  Description: 'Check for duplicate keys in hash literals.'
1408
1414
  Enabled: true
@@ -2179,17 +2185,18 @@ Naming/MethodParameterName:
2179
2185
  AllowNamesEndingInNumbers: true
2180
2186
  # Allowed names that will not register an offense
2181
2187
  AllowedNames:
2182
- - io
2183
- - id
2184
- - to
2188
+ - at
2185
2189
  - by
2186
- - 'on'
2190
+ - db
2191
+ - id
2187
2192
  - in
2188
- - at
2193
+ - io
2189
2194
  - ip
2190
- - db
2195
+ - of
2196
+ - 'on'
2191
2197
  - os
2192
2198
  - pp
2199
+ - to
2193
2200
  # Forbidden names that will register an offense
2194
2201
  ForbiddenNames: []
2195
2202
 
@@ -2340,6 +2347,14 @@ Style/AndOr:
2340
2347
  - always
2341
2348
  - conditionals
2342
2349
 
2350
+ Style/ArrayCoercion:
2351
+ Description: >-
2352
+ Use Array() instead of explicit Array check or [*var], when dealing
2353
+ with a variable you want to treat as an Array, but you're not certain it's an array.
2354
+ StyleGuide: '#array-coercion'
2355
+ Enabled: 'pending'
2356
+ VersionAdded: '0.88'
2357
+
2343
2358
  Style/ArrayJoin:
2344
2359
  Description: 'Use Array#join instead of Array#*.'
2345
2360
  StyleGuide: '#array-join'
@@ -2522,6 +2537,12 @@ Style/CaseEquality:
2522
2537
  # String === "string"
2523
2538
  AllowOnConstant: false
2524
2539
 
2540
+ Style/CaseLikeIf:
2541
+ Description: 'This cop identifies places where `if-elsif` constructions can be replaced with `case-when`.'
2542
+ StyleGuide: '#case-vs-if-else'
2543
+ Enabled: 'pending'
2544
+ VersionAdded: '0.88'
2545
+
2525
2546
  Style/CharacterLiteral:
2526
2547
  Description: 'Checks for uses of character literals.'
2527
2548
  StyleGuide: '#no-character-literals'
@@ -2961,6 +2982,18 @@ Style/GuardClause:
2961
2982
  # needs to have to trigger this cop
2962
2983
  MinBodyLength: 1
2963
2984
 
2985
+ Style/HashAsLastArrayItem:
2986
+ Description: >-
2987
+ Checks for presence or absence of braces around hash literal as a last
2988
+ array item depending on configuration.
2989
+ StyleGuide: '#hash-literal-as-last-array-item'
2990
+ Enabled: 'pending'
2991
+ VersionAdded: '0.88'
2992
+ EnforcedStyle: braces
2993
+ SupportedStyles:
2994
+ - braces
2995
+ - no_braces
2996
+
2964
2997
  Style/HashEachMethods:
2965
2998
  Description: 'Use Hash#each_key and Hash#each_value.'
2966
2999
  StyleGuide: '#hash-each'
@@ -2968,6 +3001,16 @@ Style/HashEachMethods:
2968
3001
  VersionAdded: '0.80'
2969
3002
  Safe: false
2970
3003
 
3004
+ Style/HashLikeCase:
3005
+ Description: >-
3006
+ Checks for places where `case-when` represents a simple 1:1
3007
+ mapping and can be replaced with a hash lookup.
3008
+ Enabled: 'pending'
3009
+ VersionAdded: '0.88'
3010
+ # `MinBranchesCount` defines the number of branches `case` needs to have
3011
+ # to trigger this cop
3012
+ MinBranchesCount: 3
3013
+
2971
3014
  Style/HashSyntax:
2972
3015
  Description: >-
2973
3016
  Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax
@@ -3665,6 +3708,14 @@ Style/RedundantFetchBlock:
3665
3708
  SafeForConstants: false
3666
3709
  VersionAdded: '0.86'
3667
3710
 
3711
+ Style/RedundantFileExtensionInRequire:
3712
+ Description: >-
3713
+ Checks for the presence of superfluous `.rb` extension in
3714
+ the filename provided to `require` and `require_relative`.
3715
+ StyleGuide: '#no-explicit-rb-to-require'
3716
+ Enabled: 'pending'
3717
+ VersionAdded: '0.88'
3718
+
3668
3719
  Style/RedundantFreeze:
3669
3720
  Description: "Checks usages of Object#freeze on immutable objects."
3670
3721
  Enabled: true
@@ -251,6 +251,7 @@ require_relative 'rubocop/cop/lint/deprecated_class_methods'
251
251
  require_relative 'rubocop/cop/lint/deprecated_open_ssl_constant'
252
252
  require_relative 'rubocop/cop/lint/disjunctive_assignment_in_constructor'
253
253
  require_relative 'rubocop/cop/lint/duplicate_case_condition'
254
+ require_relative 'rubocop/cop/lint/duplicate_elsif_condition'
254
255
  require_relative 'rubocop/cop/lint/duplicate_hash_key'
255
256
  require_relative 'rubocop/cop/lint/duplicate_methods'
256
257
  require_relative 'rubocop/cop/lint/each_with_object_argument'
@@ -360,6 +361,7 @@ require_relative 'rubocop/cop/style/access_modifier_declarations'
360
361
  require_relative 'rubocop/cop/style/accessor_grouping'
361
362
  require_relative 'rubocop/cop/style/alias'
362
363
  require_relative 'rubocop/cop/style/and_or'
364
+ require_relative 'rubocop/cop/style/array_coercion'
363
365
  require_relative 'rubocop/cop/style/array_join'
364
366
  require_relative 'rubocop/cop/style/ascii_comments'
365
367
  require_relative 'rubocop/cop/style/attr'
@@ -370,6 +372,7 @@ require_relative 'rubocop/cop/style/bisected_attr_accessor'
370
372
  require_relative 'rubocop/cop/style/block_comments'
371
373
  require_relative 'rubocop/cop/style/block_delimiters'
372
374
  require_relative 'rubocop/cop/style/case_equality'
375
+ require_relative 'rubocop/cop/style/case_like_if'
373
376
  require_relative 'rubocop/cop/style/character_literal'
374
377
  require_relative 'rubocop/cop/style/class_and_module_children'
375
378
  require_relative 'rubocop/cop/style/class_check'
@@ -413,7 +416,9 @@ require_relative 'rubocop/cop/style/format_string_token'
413
416
  require_relative 'rubocop/cop/style/frozen_string_literal_comment'
414
417
  require_relative 'rubocop/cop/style/global_vars'
415
418
  require_relative 'rubocop/cop/style/guard_clause'
419
+ require_relative 'rubocop/cop/style/hash_as_last_array_item'
416
420
  require_relative 'rubocop/cop/style/hash_each_methods'
421
+ require_relative 'rubocop/cop/style/hash_like_case'
417
422
  require_relative 'rubocop/cop/style/hash_syntax'
418
423
  require_relative 'rubocop/cop/style/hash_transform_keys'
419
424
  require_relative 'rubocop/cop/style/hash_transform_values'
@@ -434,6 +439,7 @@ require_relative 'rubocop/cop/style/method_call_without_args_parentheses'
434
439
  require_relative 'rubocop/cop/style/method_call_with_args_parentheses'
435
440
  require_relative 'rubocop/cop/style/redundant_assignment'
436
441
  require_relative 'rubocop/cop/style/redundant_fetch_block'
442
+ require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
437
443
  require_relative 'rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses'
438
444
  require_relative 'rubocop/cop/style/method_call_with_args_parentheses/require_parentheses'
439
445
  require_relative 'rubocop/cop/style/method_called_on_do_end_block'
@@ -75,7 +75,7 @@ module RuboCop
75
75
 
76
76
  def validate_options_vs_config
77
77
  if @options[:parallel] &&
78
- !@config_store.for_dir(Dir.pwd).for_all_cops['UseCache']
78
+ !@config_store.for_pwd.for_all_cops['UseCache']
79
79
  raise OptionArgumentError, '-P/--parallel uses caching to speed up ' \
80
80
  'execution, so combining with AllCops: ' \
81
81
  'UseCache: false is not allowed.'
@@ -121,7 +121,7 @@ module RuboCop
121
121
  if @options[:auto_gen_config]
122
122
  formatter = 'autogenconf'
123
123
  else
124
- cfg = @config_store.for_dir(Dir.pwd).for_all_cops
124
+ cfg = @config_store.for_pwd.for_all_cops
125
125
  formatter = cfg['DefaultFormatter'] || 'progress'
126
126
  end
127
127
  [[formatter, @options[:output_path]]]
@@ -27,10 +27,10 @@ module RuboCop
27
27
  private
28
28
 
29
29
  def maybe_run_line_length_cop
30
- if !line_length_enabled?(@config_store.for_dir(Dir.pwd))
30
+ if !line_length_enabled?(@config_store.for_pwd)
31
31
  skip_line_length_cop(PHASE_1_DISABLED)
32
32
  elsif !same_max_line_length?(
33
- @config_store.for_dir(Dir.pwd), ConfigLoader.default_configuration
33
+ @config_store.for_pwd, ConfigLoader.default_configuration
34
34
  )
35
35
  skip_line_length_cop(PHASE_1_OVERRIDDEN)
36
36
  else
@@ -24,7 +24,7 @@ module RuboCop
24
24
 
25
25
  attr_accessor :debug, :ignore_parent_exclusion,
26
26
  :disable_pending_cops, :enable_pending_cops
27
- attr_writer :default_configuration
27
+ attr_writer :default_configuration, :project_root
28
28
 
29
29
  alias debug? debug
30
30
  alias ignore_parent_exclusion? ignore_parent_exclusion
@@ -118,14 +118,13 @@ module RuboCop
118
118
  end
119
119
 
120
120
  def add_excludes_from_files(config, config_file)
121
- found_files = find_files_upwards(DOTFILE, config_file)
121
+ exclusion_file = find_last_file_upwards(DOTFILE, config_file, project_root)
122
122
 
123
- return if found_files.empty?
124
- return if PathUtil.relative_path(found_files.last) ==
125
- PathUtil.relative_path(config_file)
123
+ return unless exclusion_file
124
+ return if PathUtil.relative_path(exclusion_file) == PathUtil.relative_path(config_file)
126
125
 
127
126
  print 'AllCops/Exclude ' if debug?
128
- config.add_excludes_from_higher_level(load_file(found_files.last))
127
+ config.add_excludes_from_higher_level(load_file(exclusion_file))
129
128
  end
130
129
 
131
130
  def default_configuration
@@ -135,6 +134,12 @@ module RuboCop
135
134
  end
136
135
  end
137
136
 
137
+ # Returns the path rubocop inferred as the root of the project. No file
138
+ # searches will go past this directory.
139
+ def project_root
140
+ @project_root ||= find_project_root
141
+ end
142
+
138
143
  def warn_on_pending_cops(pending_cops)
139
144
  return if pending_cops.empty?
140
145
 
@@ -159,7 +164,15 @@ module RuboCop
159
164
  private
160
165
 
161
166
  def find_project_dotfile(target_dir)
162
- find_file_upwards(DOTFILE, target_dir)
167
+ find_file_upwards(DOTFILE, target_dir, project_root)
168
+ end
169
+
170
+ def find_project_root
171
+ pwd = Dir.pwd
172
+ gems_file = find_last_file_upwards('Gemfile', pwd) || find_last_file_upwards('gems.rb', pwd)
173
+ return unless gems_file
174
+
175
+ File.dirname(gems_file)
163
176
  end
164
177
 
165
178
  def find_user_dotfile
@@ -33,6 +33,10 @@ module RuboCop
33
33
  for_dir(File.dirname(file))
34
34
  end
35
35
 
36
+ def for_pwd
37
+ for_dir(Dir.pwd)
38
+ end
39
+
36
40
  # If type (file/dir) is known beforehand,
37
41
  # prefer using #for_file or #for_dir for improved performance
38
42
  def for(file_or_dir)
@@ -73,7 +73,7 @@ module RuboCop
73
73
  end
74
74
 
75
75
  def max_line_length
76
- config.for_cop('Layout/LineLength')['Max'] || 80
76
+ config.for_cop('Layout/LineLength')['Max'] || 120
77
77
  end
78
78
 
79
79
  def disable_offense_at_end_of_line(range, eol_comment)
@@ -58,7 +58,7 @@ module RuboCop
58
58
  end
59
59
 
60
60
  def to_s
61
- qualified? ? "#{department}/#{cop_name}" : cop_name
61
+ @to_s ||= qualified? ? "#{department}/#{cop_name}" : cop_name
62
62
  end
63
63
 
64
64
  def qualified?
@@ -105,7 +105,7 @@ module RuboCop
105
105
  # If message is not specified, the method `message` will be called.
106
106
  def add_offense(node_or_range, message: nil, severity: nil, &block)
107
107
  range = range_from_node_or_range(node_or_range)
108
- return unless @current_offense_locations.add?(range)
108
+ return unless current_offense_locations.add?(range)
109
109
 
110
110
  range_to_pass = callback_argument(range)
111
111
 
@@ -271,11 +271,19 @@ module RuboCop
271
271
 
272
272
  ### Reserved for Commissioner:
273
273
 
274
+ def current_offense_locations
275
+ @current_offense_locations ||= Set.new
276
+ end
277
+
278
+ def currently_disabled_lines
279
+ @currently_disabled_lines ||= Set.new
280
+ end
281
+
274
282
  # Called before any investigation
275
283
  def begin_investigation(processed_source)
276
284
  @current_offenses = []
277
- @current_offense_locations = Set[]
278
- @currently_disabled_lines = Set[]
285
+ @current_offense_locations = nil
286
+ @currently_disabled_lines = nil
279
287
  @processed_source = processed_source
280
288
  @current_corrector = Corrector.new(@processed_source) if @processed_source.valid_syntax?
281
289
  end
@@ -327,7 +335,7 @@ module RuboCop
327
335
 
328
336
  def disable_uncorrectable(range)
329
337
  line = range.line
330
- return unless @currently_disabled_lines.add?(line)
338
+ return unless currently_disabled_lines.add?(line)
331
339
 
332
340
  disable_offense(range)
333
341
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'uri'
4
- require_relative 'legacy/corrections_proxy.rb'
4
+ require_relative 'legacy/corrections_proxy'
5
5
 
6
6
  module RuboCop
7
7
  module Cop
@@ -42,8 +42,34 @@ module RuboCop
42
42
 
43
43
  corrector.insert_before(
44
44
  last_element_range_with_trailing_comma(node).end,
45
+ content_if_comment_present(corrector, node)
46
+ )
47
+ end
48
+
49
+ def content_if_comment_present(corrector, node)
50
+ range = range_with_surrounding_space(
51
+ range: children(node).last.source_range,
52
+ side: :right
53
+ ).end.resize(1)
54
+ if range.source == '#'
55
+ select_content_to_be_inserted_after_last_element(corrector, node)
56
+ else
45
57
  node.loc.end.source
58
+ end
59
+ end
60
+
61
+ def select_content_to_be_inserted_after_last_element(corrector, node)
62
+ range = range_between(
63
+ node.loc.end.begin_pos,
64
+ range_by_whole_lines(node.loc.expression).end.end_pos
46
65
  )
66
+
67
+ remove_trailing_content_of_comment(corrector, range)
68
+ range.source
69
+ end
70
+
71
+ def remove_trailing_content_of_comment(corrector, range)
72
+ corrector.remove(range)
47
73
  end
48
74
 
49
75
  def last_element_range_with_trailing_comma(node)
@@ -35,6 +35,11 @@ module RuboCop
35
35
  # Gem::Specification.new do |spec|
36
36
  # spec.required_ruby_version = ['>= 2.5.0', '< 2.7.0']
37
37
  # end
38
+ #
39
+ # # good
40
+ # Gem::Specification.new do |spec|
41
+ # spec.required_ruby_version = '~> 2.5'
42
+ # end
38
43
  class RequiredRubyVersion < Cop
39
44
  MSG = '`required_ruby_version` (%<required_ruby_version>s, ' \
40
45
  'declared in %<gemspec_filename>s) and `TargetRubyVersion` ' \
@@ -68,7 +73,7 @@ module RuboCop
68
73
  end
69
74
  end
70
75
 
71
- required_ruby_version.str_content.match(/(\d\.\d)/)[1]
76
+ required_ruby_version.str_content.scan(/\d/).first(2).join('.')
72
77
  end
73
78
 
74
79
  def message(required_ruby_version, target_ruby_version)
@@ -109,6 +109,7 @@ module RuboCop
109
109
 
110
110
  def allowed_only_before_style?(node)
111
111
  if node.special_modifier?
112
+ return true if processed_source[node.last_line] == 'end'
112
113
  return false if next_line_empty?(node.last_line)
113
114
  end
114
115