rubocop 1.0.0 → 1.1.0
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.
- 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
|