rubocop 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -5
- data/config/default.yml +52 -3
- data/lib/rubocop.rb +8 -0
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +23 -3
- data/lib/rubocop/cop/commissioner.rb +9 -9
- data/lib/rubocop/cop/corrector.rb +3 -1
- data/lib/rubocop/cop/force.rb +1 -1
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -2
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +2 -3
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +77 -0
- data/lib/rubocop/cop/lint/empty_block.rb +46 -0
- data/lib/rubocop/cop/lint/flip_flop.rb +8 -2
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +17 -3
- data/lib/rubocop/cop/lint/number_conversion.rb +46 -13
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +27 -8
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +95 -0
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +185 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -1
- data/lib/rubocop/cop/offense.rb +3 -3
- data/lib/rubocop/cop/style/arguments_forwarding.rb +142 -0
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +67 -0
- data/lib/rubocop/cop/style/multiple_comparison.rb +54 -7
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +7 -1
- data/lib/rubocop/cop/style/semicolon.rb +3 -0
- data/lib/rubocop/cop/style/swap_values.rb +108 -0
- data/lib/rubocop/cop/team.rb +6 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/ext/regexp_node.rb +10 -7
- data/lib/rubocop/ext/regexp_parser.rb +77 -0
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/magic_comment.rb +2 -2
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/version.rb +1 -1
- metadata +13 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da2c7f3fe5f1a109fce4e8e9e44efd9e438c45c0c0036f79f3d0156a4dacc452
|
4
|
+
data.tar.gz: ff29fbdedc13116e5fdbcb95dc3af4a81379794f9d36596983f69a09d69ac575
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11f024ff53e3eb551b31b02c3a48ab250941c9fd0e642c3bb518a8d635bee89f0fc61dba12e0a66ac40c4536bf368690ade37ce3a6014531ad97ebc0fd9d82f8
|
7
|
+
data.tar.gz: e567372e804699a2499b6475cdeb4e86906c5fe8eda16428d292a600648d2afe2d34bacea2443fe52229ce4539b5a09b17f387586fc3a9e2d3034d3718ce4bb3
|
data/README.md
CHANGED
@@ -43,15 +43,18 @@ If you'd rather install RuboCop using `bundler`, add a line for it in your `Gemf
|
|
43
43
|
gem 'rubocop', require: false
|
44
44
|
```
|
45
45
|
|
46
|
-
RuboCop
|
47
|
-
|
48
|
-
|
49
|
-
might want to use a conservative version lock
|
46
|
+
RuboCop is stable between major versions, both in terms of API and cop configuration.
|
47
|
+
We aim the ease the maintenance of RuboCop extensions and the upgrades between RuboCop
|
48
|
+
releases. All big changes are reserved for major releases.
|
49
|
+
To prevent an unwanted RuboCop update you might want to use a conservative version lock
|
50
|
+
in your `Gemfile`:
|
50
51
|
|
51
52
|
```rb
|
52
|
-
gem 'rubocop', '~> 1.
|
53
|
+
gem 'rubocop', '~> 1.1', require: false
|
53
54
|
```
|
54
55
|
|
56
|
+
See [versioning](https://docs.rubocop.org/rubocop/1.0/versioning.html) for further details.
|
57
|
+
|
55
58
|
## Quickstart
|
56
59
|
|
57
60
|
Just type `rubocop` in a Ruby project's folder and watch the magic happen.
|
data/config/default.yml
CHANGED
@@ -1334,7 +1334,7 @@ Layout/TrailingWhitespace:
|
|
1334
1334
|
StyleGuide: '#no-trailing-whitespace'
|
1335
1335
|
Enabled: true
|
1336
1336
|
VersionAdded: '0.49'
|
1337
|
-
VersionChanged: '0
|
1337
|
+
VersionChanged: '1.0'
|
1338
1338
|
AllowInHeredoc: false
|
1339
1339
|
|
1340
1340
|
#################### Lint ##################################
|
@@ -1454,6 +1454,11 @@ Lint/DuplicateMethods:
|
|
1454
1454
|
Enabled: true
|
1455
1455
|
VersionAdded: '0.29'
|
1456
1456
|
|
1457
|
+
Lint/DuplicateRegexpCharacterClassElement:
|
1458
|
+
Description: 'Checks for duplicate elements in Regexp character classes.'
|
1459
|
+
Enabled: pending
|
1460
|
+
VersionAdded: '1.1'
|
1461
|
+
|
1457
1462
|
Lint/DuplicateRequire:
|
1458
1463
|
Description: 'Check for duplicate `require`s and `require_relative`s.'
|
1459
1464
|
Enabled: true
|
@@ -1474,6 +1479,12 @@ Lint/ElseLayout:
|
|
1474
1479
|
Enabled: true
|
1475
1480
|
VersionAdded: '0.17'
|
1476
1481
|
|
1482
|
+
Lint/EmptyBlock:
|
1483
|
+
Description: 'This cop checks for blocks without a body.'
|
1484
|
+
Enabled: pending
|
1485
|
+
VersionAdded: '1.1'
|
1486
|
+
AllowComments: true
|
1487
|
+
|
1477
1488
|
Lint/EmptyConditionalBody:
|
1478
1489
|
Description: 'This cop checks for the presence of `if`, `elsif` and `unless` branches without a body.'
|
1479
1490
|
Enabled: true
|
@@ -1647,7 +1658,8 @@ Lint/MultipleComparison:
|
|
1647
1658
|
Description: "Use `&&` operator to compare multiple values."
|
1648
1659
|
Enabled: true
|
1649
1660
|
VersionAdded: '0.47'
|
1650
|
-
VersionChanged: '
|
1661
|
+
VersionChanged: '1.1'
|
1662
|
+
AllowMethodComparison: true
|
1651
1663
|
|
1652
1664
|
Lint/NestedMethodDefinition:
|
1653
1665
|
Description: 'Do not use nested method definitions.'
|
@@ -1682,8 +1694,12 @@ Lint/NumberConversion:
|
|
1682
1694
|
Description: 'Checks unsafe usage of number conversion methods.'
|
1683
1695
|
Enabled: false
|
1684
1696
|
VersionAdded: '0.53'
|
1685
|
-
VersionChanged: '
|
1697
|
+
VersionChanged: '1.1'
|
1686
1698
|
SafeAutoCorrect: false
|
1699
|
+
IgnoredMethods: []
|
1700
|
+
IgnoredClasses:
|
1701
|
+
- Time
|
1702
|
+
- DateTime
|
1687
1703
|
|
1688
1704
|
Lint/OrderedMagicComments:
|
1689
1705
|
Description: 'Checks the proper ordering of magic comments and whether a magic comment is not placed before a shebang.'
|
@@ -1910,6 +1926,11 @@ Lint/Syntax:
|
|
1910
1926
|
VersionAdded: '0.9'
|
1911
1927
|
|
1912
1928
|
|
1929
|
+
Lint/ToEnumArguments:
|
1930
|
+
Description: 'This cop ensures that `to_enum`/`enum_for`, called for the current method, has correct arguments.'
|
1931
|
+
Enabled: pending
|
1932
|
+
VersionAdded: '1.1'
|
1933
|
+
|
1913
1934
|
Lint/ToJSON:
|
1914
1935
|
Description: 'Ensure #to_json includes an optional argument.'
|
1915
1936
|
Enabled: true
|
@@ -1936,6 +1957,11 @@ Lint/UnifiedInteger:
|
|
1936
1957
|
Enabled: true
|
1937
1958
|
VersionAdded: '0.43'
|
1938
1959
|
|
1960
|
+
Lint/UnmodifiedReduceAccumulator:
|
1961
|
+
Description: Checks for `reduce` or `inject` blocks that do not update the accumulator each iteration.
|
1962
|
+
Enabled: pending
|
1963
|
+
VersionAdded: '1.1'
|
1964
|
+
|
1939
1965
|
Lint/UnreachableCode:
|
1940
1966
|
Description: 'Unreachable code.'
|
1941
1967
|
Enabled: true
|
@@ -2478,6 +2504,13 @@ Style/AndOr:
|
|
2478
2504
|
- always
|
2479
2505
|
- conditionals
|
2480
2506
|
|
2507
|
+
Style/ArgumentsForwarding:
|
2508
|
+
Description: 'Use arguments forwarding.'
|
2509
|
+
StyleGuide: '#arguments-forwarding'
|
2510
|
+
Enabled: pending
|
2511
|
+
AllowOnlyRestArgument: true
|
2512
|
+
VersionAdded: '1.1'
|
2513
|
+
|
2481
2514
|
Style/ArrayCoercion:
|
2482
2515
|
Description: >-
|
2483
2516
|
Use Array() instead of explicit Array check or [*var], when dealing
|
@@ -2918,6 +2951,14 @@ Style/DisableCopsWithinSourceCodeDirective:
|
|
2918
2951
|
Enabled: false
|
2919
2952
|
VersionAdded: '0.82'
|
2920
2953
|
|
2954
|
+
Style/DocumentDynamicEvalDefinition:
|
2955
|
+
Description: >-
|
2956
|
+
When using `class_eval` (or other `eval`) with string interpolation,
|
2957
|
+
add a comment block showing its appearance if interpolated.
|
2958
|
+
StyleGuide: '#eval-comment-docs'
|
2959
|
+
Enabled: pending
|
2960
|
+
VersionAdded: '1.1'
|
2961
|
+
|
2921
2962
|
Style/Documentation:
|
2922
2963
|
Description: 'Document classes and non-namespace modules.'
|
2923
2964
|
Enabled: true
|
@@ -3535,6 +3576,7 @@ Style/MultipleComparison:
|
|
3535
3576
|
use Array#include? instead.
|
3536
3577
|
Enabled: true
|
3537
3578
|
VersionAdded: '0.49'
|
3579
|
+
VersionChanged: '1.1'
|
3538
3580
|
|
3539
3581
|
Style/MutableConstant:
|
3540
3582
|
Description: 'Do not assign mutable objects to constants.'
|
@@ -4226,6 +4268,13 @@ Style/StructInheritance:
|
|
4226
4268
|
VersionAdded: '0.29'
|
4227
4269
|
VersionChanged: '0.86'
|
4228
4270
|
|
4271
|
+
Style/SwapValues:
|
4272
|
+
Description: 'This cop enforces the use of shorthand-style swapping of 2 variables.'
|
4273
|
+
StyleGuide: '#values-swapping'
|
4274
|
+
Enabled: pending
|
4275
|
+
VersionAdded: '1.1'
|
4276
|
+
SafeAutoCorrect: false
|
4277
|
+
|
4229
4278
|
Style/SymbolArray:
|
4230
4279
|
Description: 'Use %i or %I for arrays of symbols.'
|
4231
4280
|
StyleGuide: '#percent-i'
|
data/lib/rubocop.rb
CHANGED
@@ -15,6 +15,7 @@ require 'rubocop-ast'
|
|
15
15
|
|
16
16
|
require_relative 'rubocop/ast_aliases'
|
17
17
|
require_relative 'rubocop/ext/regexp_node'
|
18
|
+
require_relative 'rubocop/ext/regexp_parser'
|
18
19
|
|
19
20
|
require_relative 'rubocop/core_ext/string'
|
20
21
|
require_relative 'rubocop/ext/processed_source'
|
@@ -262,10 +263,12 @@ require_relative 'rubocop/cop/lint/duplicate_case_condition'
|
|
262
263
|
require_relative 'rubocop/cop/lint/duplicate_elsif_condition'
|
263
264
|
require_relative 'rubocop/cop/lint/duplicate_hash_key'
|
264
265
|
require_relative 'rubocop/cop/lint/duplicate_methods'
|
266
|
+
require_relative 'rubocop/cop/lint/duplicate_regexp_character_class_element'
|
265
267
|
require_relative 'rubocop/cop/lint/duplicate_require'
|
266
268
|
require_relative 'rubocop/cop/lint/duplicate_rescue_exception'
|
267
269
|
require_relative 'rubocop/cop/lint/each_with_object_argument'
|
268
270
|
require_relative 'rubocop/cop/lint/else_layout'
|
271
|
+
require_relative 'rubocop/cop/lint/empty_block'
|
269
272
|
require_relative 'rubocop/cop/lint/empty_conditional_body'
|
270
273
|
require_relative 'rubocop/cop/lint/empty_ensure'
|
271
274
|
require_relative 'rubocop/cop/lint/empty_expression'
|
@@ -330,11 +333,13 @@ require_relative 'rubocop/cop/lint/shadowing_outer_local_variable'
|
|
330
333
|
require_relative 'rubocop/cop/lint/struct_new_override'
|
331
334
|
require_relative 'rubocop/cop/lint/suppressed_exception'
|
332
335
|
require_relative 'rubocop/cop/lint/syntax'
|
336
|
+
require_relative 'rubocop/cop/lint/to_enum_arguments'
|
333
337
|
require_relative 'rubocop/cop/lint/to_json'
|
334
338
|
require_relative 'rubocop/cop/lint/top_level_return_with_argument'
|
335
339
|
require_relative 'rubocop/cop/lint/trailing_comma_in_attribute_declaration'
|
336
340
|
require_relative 'rubocop/cop/lint/underscore_prefixed_variable_name'
|
337
341
|
require_relative 'rubocop/cop/lint/unified_integer'
|
342
|
+
require_relative 'rubocop/cop/lint/unmodified_reduce_accumulator'
|
338
343
|
require_relative 'rubocop/cop/lint/unreachable_code'
|
339
344
|
require_relative 'rubocop/cop/lint/unreachable_loop'
|
340
345
|
require_relative 'rubocop/cop/lint/unused_block_argument'
|
@@ -384,6 +389,7 @@ require_relative 'rubocop/cop/style/access_modifier_declarations'
|
|
384
389
|
require_relative 'rubocop/cop/style/accessor_grouping'
|
385
390
|
require_relative 'rubocop/cop/style/alias'
|
386
391
|
require_relative 'rubocop/cop/style/and_or'
|
392
|
+
require_relative 'rubocop/cop/style/arguments_forwarding'
|
387
393
|
require_relative 'rubocop/cop/style/array_coercion'
|
388
394
|
require_relative 'rubocop/cop/style/array_join'
|
389
395
|
require_relative 'rubocop/cop/style/ascii_comments'
|
@@ -419,6 +425,7 @@ require_relative 'rubocop/cop/style/dir'
|
|
419
425
|
require_relative 'rubocop/cop/style/disable_cops_within_source_code_directive'
|
420
426
|
require_relative 'rubocop/cop/style/documentation_method'
|
421
427
|
require_relative 'rubocop/cop/style/documentation'
|
428
|
+
require_relative 'rubocop/cop/style/document_dynamic_eval_definition'
|
422
429
|
require_relative 'rubocop/cop/style/double_cop_disable_directive'
|
423
430
|
require_relative 'rubocop/cop/style/double_negation'
|
424
431
|
require_relative 'rubocop/cop/style/each_for_simple_loop'
|
@@ -554,6 +561,7 @@ require_relative 'rubocop/cop/style/string_literals_in_interpolation'
|
|
554
561
|
require_relative 'rubocop/cop/style/string_methods'
|
555
562
|
require_relative 'rubocop/cop/style/strip'
|
556
563
|
require_relative 'rubocop/cop/style/struct_inheritance'
|
564
|
+
require_relative 'rubocop/cop/style/swap_values'
|
557
565
|
require_relative 'rubocop/cop/style/symbol_array'
|
558
566
|
require_relative 'rubocop/cop/style/symbol_literal'
|
559
567
|
require_relative 'rubocop/cop/style/symbol_proc'
|
@@ -90,7 +90,7 @@ module RuboCop
|
|
90
90
|
def reset_config_and_auto_gen_file
|
91
91
|
@config_store = ConfigStore.new
|
92
92
|
@config_store.options_config = @options[:config] if @options[:config]
|
93
|
-
File.open(AUTO_GENERATED_FILE, 'w') {}
|
93
|
+
File.open(AUTO_GENERATED_FILE, 'w') {} # create or truncate if exists
|
94
94
|
add_inheritance_from_auto_generated_file(@options[:config])
|
95
95
|
end
|
96
96
|
|
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
REDUNDANT_DISABLE = 'Lint/RedundantCopDisableDirective'
|
9
9
|
|
10
10
|
# @api private
|
11
|
-
COP_NAME_PATTERN = '([A-Z]\w+/)
|
11
|
+
COP_NAME_PATTERN = '([A-Z]\w+/)*(?:[A-Z]\w+)'
|
12
12
|
# @api private
|
13
13
|
COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}"
|
14
14
|
# @api private
|
@@ -25,6 +25,16 @@ module RuboCop
|
|
25
25
|
#
|
26
26
|
# # good
|
27
27
|
# gem 'rubocop', groups: [:development, :test]
|
28
|
+
#
|
29
|
+
# # good - conditional declaration
|
30
|
+
# if Dir.exist?(local)
|
31
|
+
# gem 'rubocop', path: local
|
32
|
+
# elsif ENV['RUBOCOP_VERSION'] == 'master'
|
33
|
+
# gem 'rubocop', git: 'https://github.com/rubocop-hq/rubocop.git'
|
34
|
+
# else
|
35
|
+
# gem 'rubocop', '~> 0.90.0'
|
36
|
+
# end
|
37
|
+
#
|
28
38
|
class DuplicatedGem < Cop
|
29
39
|
include RangeHelp
|
30
40
|
|
@@ -53,11 +63,21 @@ module RuboCop
|
|
53
63
|
gem_declarations(processed_source.ast)
|
54
64
|
.group_by(&:first_argument)
|
55
65
|
.values
|
56
|
-
.select { |nodes| nodes.size > 1 && !
|
66
|
+
.select { |nodes| nodes.size > 1 && !conditional_declaration?(nodes) }
|
57
67
|
end
|
58
68
|
|
59
|
-
def
|
60
|
-
|
69
|
+
def conditional_declaration?(nodes)
|
70
|
+
parent = nodes[0].parent
|
71
|
+
return false unless parent&.if_type? || parent&.when_type?
|
72
|
+
|
73
|
+
root_conditional_node = parent.if_type? ? parent : parent.parent
|
74
|
+
nodes.all? { |node| within_conditional?(node, root_conditional_node) }
|
75
|
+
end
|
76
|
+
|
77
|
+
def within_conditional?(node, conditional_node)
|
78
|
+
conditional_node.branches.any? do |branch|
|
79
|
+
branch == node || branch.child_nodes.include?(node)
|
80
|
+
end
|
61
81
|
end
|
62
82
|
|
63
83
|
def register_offense(node, gem_name, line_of_first_occurrence)
|
@@ -65,13 +65,13 @@ module RuboCop
|
|
65
65
|
c = '#' if NO_CHILD_NODES.include?(node_type) # has Children?
|
66
66
|
|
67
67
|
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
68
|
-
def on_#{node_type}(node)
|
69
|
-
trigger_responding_cops(:on_#{node_type}, node)
|
70
|
-
#{r} trigger_restricted_cops(:on_#{node_type}, node)
|
71
|
-
#{c} super(node)
|
72
|
-
#{c} trigger_responding_cops(:after_#{node_type}, node)
|
73
|
-
#{c}#{r} trigger_restricted_cops(:after_#{node_type}, node)
|
74
|
-
end
|
68
|
+
def on_#{node_type}(node) # def on_send(node)
|
69
|
+
trigger_responding_cops(:on_#{node_type}, node) # trigger_responding_cops(:on_send, node)
|
70
|
+
#{r} trigger_restricted_cops(:on_#{node_type}, node) # trigger_restricted_cops(:on_send, node)
|
71
|
+
#{c} super(node) # super(node)
|
72
|
+
#{c} trigger_responding_cops(:after_#{node_type}, node) # trigger_responding_cops(:after_send, node)
|
73
|
+
#{c}#{r} trigger_restricted_cops(:after_#{node_type}, node) # trigger_restricted_cops(:after_send, node)
|
74
|
+
end # end
|
75
75
|
RUBY
|
76
76
|
end
|
77
77
|
|
@@ -97,7 +97,7 @@ module RuboCop
|
|
97
97
|
def trigger_responding_cops(callback, node)
|
98
98
|
@callbacks[callback]&.each do |cop|
|
99
99
|
with_cop_error_handling(cop, node) do
|
100
|
-
cop.
|
100
|
+
cop.public_send(callback, node)
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
@@ -133,7 +133,7 @@ module RuboCop
|
|
133
133
|
name = node.method_name
|
134
134
|
@restricted_map[event][name]&.each do |cop|
|
135
135
|
with_cop_error_handling(cop, node) do
|
136
|
-
cop.
|
136
|
+
cop.public_send(event, node)
|
137
137
|
end
|
138
138
|
end
|
139
139
|
end
|
@@ -9,6 +9,8 @@ module RuboCop
|
|
9
9
|
# The nodes modified by the corrections should be part of the
|
10
10
|
# AST of the source_buffer.
|
11
11
|
class Corrector < ::Parser::Source::TreeRewriter
|
12
|
+
NOOP_CONSUMER = ->(diagnostic) {} # noop
|
13
|
+
|
12
14
|
# @param source [Parser::Source::Buffer, or anything
|
13
15
|
# leading to one via `(processed_source.)buffer`]
|
14
16
|
#
|
@@ -23,7 +25,7 @@ module RuboCop
|
|
23
25
|
)
|
24
26
|
|
25
27
|
# Don't print warnings to stderr if corrections conflict with each other
|
26
|
-
diagnostics.consumer =
|
28
|
+
diagnostics.consumer = NOOP_CONSUMER
|
27
29
|
end
|
28
30
|
|
29
31
|
alias rewrite process # Legacy
|
data/lib/rubocop/cop/force.rb
CHANGED
@@ -56,8 +56,7 @@ module RuboCop
|
|
56
56
|
aligned = Set[locs.first.line, locs.last.line]
|
57
57
|
locs.each_cons(3) do |before, loc, after|
|
58
58
|
col = loc.column
|
59
|
-
aligned << loc.line if col == before.column ||
|
60
|
-
col == after.column
|
59
|
+
aligned << loc.line if col == before.column || col == after.column
|
61
60
|
end
|
62
61
|
aligned
|
63
62
|
end
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
range = offense_range(lineno, line)
|
64
64
|
add_offense(range) do |corrector|
|
65
65
|
if heredoc
|
66
|
-
corrector.
|
66
|
+
corrector.wrap(range, "\#{'", "'}") unless static?(heredoc)
|
67
67
|
else
|
68
68
|
corrector.remove(range)
|
69
69
|
end
|
@@ -37,7 +37,7 @@ module RuboCop
|
|
37
37
|
|
38
38
|
RESTRICT_ON_SEND = %i[
|
39
39
|
debugger byebug remote_byebug pry remote_pry pry_remote console rescue
|
40
|
-
save_and_open_page save_and_open_screenshot
|
40
|
+
save_and_open_page save_and_open_screenshot irb
|
41
41
|
].freeze
|
42
42
|
|
43
43
|
def_node_matcher :kernel?, <<~PATTERN
|
@@ -53,8 +53,7 @@ module RuboCop
|
|
53
53
|
{:pry :remote_pry :pry_remote :console} ...)
|
54
54
|
(send (const {nil? (cbase)} :Pry) :rescue ...)
|
55
55
|
(send nil? {:save_and_open_page
|
56
|
-
:save_and_open_screenshot
|
57
|
-
:save_screenshot} ...)}
|
56
|
+
:save_and_open_screenshot} ...)}
|
58
57
|
PATTERN
|
59
58
|
|
60
59
|
def_node_matcher :binding_irb_call?, <<~PATTERN
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks for duplicate elements in Regexp character classes.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# r = /[xyx]/
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# r = /[0-9x0-9]/
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# r = /[xy]/
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# r = /[0-9x]/
|
21
|
+
class DuplicateRegexpCharacterClassElement < Base
|
22
|
+
include RangeHelp
|
23
|
+
extend AutoCorrector
|
24
|
+
|
25
|
+
MSG_REPEATED_ELEMENT = 'Duplicate element inside regexp character class'
|
26
|
+
|
27
|
+
def on_regexp(node)
|
28
|
+
each_repeated_character_class_element_loc(node) do |loc|
|
29
|
+
add_offense(loc, message: MSG_REPEATED_ELEMENT) do |corrector|
|
30
|
+
corrector.remove(loc)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def each_repeated_character_class_element_loc(node)
|
36
|
+
node.parsed_tree&.each_expression do |expr|
|
37
|
+
next if expr.type != :set || expr.token == :intersection
|
38
|
+
|
39
|
+
seen = Set.new
|
40
|
+
|
41
|
+
expr.expressions.each do |child|
|
42
|
+
next if within_interpolation?(node, child)
|
43
|
+
|
44
|
+
child_source = child.to_s
|
45
|
+
|
46
|
+
yield child.expression if seen.include?(child_source)
|
47
|
+
|
48
|
+
seen << child_source
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Since we blank interpolations with a space for every char of the interpolation, we would
|
56
|
+
# mark every space (except the first) as duplicate if we do not skip regexp_parser nodes
|
57
|
+
# that are within an interpolation.
|
58
|
+
def within_interpolation?(node, child)
|
59
|
+
parse_tree_child_loc = child.expression
|
60
|
+
|
61
|
+
interpolation_locs(node).any? { |il| il.overlaps?(parse_tree_child_loc) }
|
62
|
+
end
|
63
|
+
|
64
|
+
def interpolation_locs(node)
|
65
|
+
@interpolation_locs ||= {}
|
66
|
+
|
67
|
+
# Cache by loc, not by regexp content, as content can be repeated in multiple patterns
|
68
|
+
key = node.loc
|
69
|
+
|
70
|
+
@interpolation_locs[key] ||= node.children.select(&:begin_type?).map do |interpolation|
|
71
|
+
interpolation.loc.expression
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|