From 9cddd6b972668c0e11316cbb86536c4faa5b1c55 Mon Sep 17 00:00:00 2001 From: Owen Stephens Date: Thu, 28 May 2020 23:17:50 +0100 Subject: [PATCH] Add `Style/RedundantRegexpCharacterClass` cop ```ruby # This cop checks for unnecessary single-element Regexp character classes. # # @example # # # bad # r = /[x]/ # # # good # r = /x/ # # # bad # r = /[\s]/ # # # good # r = /\s/ # # # good # r = /[ab]/ ``` --- CHANGELOG.md | 1 + config/default.yml | 5 + docs/modules/ROOT/pages/cops.adoc | 1 + docs/modules/ROOT/pages/cops_style.adoc | 34 +++ lib/rubocop.rb | 1 + .../heredoc_argument_closing_parenthesis.rb | 2 +- lib/rubocop/cop/migration/department_name.rb | 2 +- lib/rubocop/cop/mixin/uncommunicative_name.rb | 2 +- .../style/redundant_regexp_character_class.rb | 89 ++++++++ .../redundant_regexp_character_class_spec.rb | 209 ++++++++++++++++++ spec/rubocop/options_spec.rb | 2 +- 11 files changed, 344 insertions(+), 4 deletions(-) create mode 100644 lib/rubocop/cop/style/redundant_regexp_character_class.rb create mode 100644 spec/rubocop/cop/style/redundant_regexp_character_class_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index c04d0bd8169..a694d801e5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### New features * [#6289](https://github.com/rubocop-hq/rubocop/issues/6289): Add new `CheckDefinitionPathHierarchy` option for `Naming/FileName`. ([@jschneid][]) +* [#8055](https://github.com/rubocop-hq/rubocop/pull/8055): Add new `Style/RedundantRegexpCharacterClass` cop. ([@owst][]) * [#8069](https://github.com/rubocop-hq/rubocop/issues/8069): New option for `expect_offense` to help format offense templates. ([@marcandre][]) * [#7908](https://github.com/rubocop-hq/rubocop/pull/7908): Add new `Style/RedundantRegexpEscape` cop. ([@owst][]) * [#7978](https://github.com/rubocop-hq/rubocop/pull/7978): Add new option `OnlyFor` to the `Bundler/GemComment` cop. ([@ric2b][]) diff --git a/config/default.yml b/config/default.yml index 73231e26bce..5afc43069f4 100644 --- a/config/default.yml +++ b/config/default.yml @@ -3613,6 +3613,11 @@ Style/RedundantPercentQ: Enabled: true VersionAdded: '0.76' +Style/RedundantRegexpCharacterClass: + Description: 'Checks for unnecessary single-element Regexp character classes.' + Enabled: pending + VersionAdded: '0.85' + Style/RedundantRegexpEscape: Description: 'Checks for redundant escapes in Regexps.' Enabled: pending diff --git a/docs/modules/ROOT/pages/cops.adoc b/docs/modules/ROOT/pages/cops.adoc index 46c111dff1c..58d6d606de1 100644 --- a/docs/modules/ROOT/pages/cops.adoc +++ b/docs/modules/ROOT/pages/cops.adoc @@ -437,6 +437,7 @@ In the following section you find all available cops: * xref:cops_style.adoc#styleredundantinterpolation[Style/RedundantInterpolation] * xref:cops_style.adoc#styleredundantparentheses[Style/RedundantParentheses] * xref:cops_style.adoc#styleredundantpercentq[Style/RedundantPercentQ] +* xref:cops_style.adoc#styleredundantregexpcharacterclass[Style/RedundantRegexpCharacterClass] * xref:cops_style.adoc#styleredundantregexpescape[Style/RedundantRegexpEscape] * xref:cops_style.adoc#styleredundantreturn[Style/RedundantReturn] * xref:cops_style.adoc#styleredundantself[Style/RedundantSelf] diff --git a/docs/modules/ROOT/pages/cops_style.adoc b/docs/modules/ROOT/pages/cops_style.adoc index 863667d660d..771ffe684e0 100644 --- a/docs/modules/ROOT/pages/cops_style.adoc +++ b/docs/modules/ROOT/pages/cops_style.adoc @@ -7116,6 +7116,40 @@ question = '"What did you say?"' * https://rubystyle.guide#percent-q +== Style/RedundantRegexpCharacterClass + +|=== +| Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged + +| Pending +| Yes +| Yes +| 0.85 +| - +|=== + +This cop checks for unnecessary single-element Regexp character classes. + +=== Examples + +[source,ruby] +---- +# bad +r = /[x]/ + +# good +r = /x/ + +# bad +r = /[\s]/ + +# good +r = /\s/ + +# good +r = /[ab]/ +---- + == Style/RedundantRegexpEscape |=== diff --git a/lib/rubocop.rb b/lib/rubocop.rb index 14f6169136a..a4253a5016f 100644 --- a/lib/rubocop.rb +++ b/lib/rubocop.rb @@ -476,6 +476,7 @@ require_relative 'rubocop/cop/style/redundant_interpolation' require_relative 'rubocop/cop/style/redundant_parentheses' require_relative 'rubocop/cop/style/redundant_percent_q' +require_relative 'rubocop/cop/style/redundant_regexp_character_class' require_relative 'rubocop/cop/style/redundant_regexp_escape' require_relative 'rubocop/cop/style/redundant_return' require_relative 'rubocop/cop/style/redundant_self' diff --git a/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb b/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb index cf945c03917..28c56afb942 100644 --- a/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +++ b/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb @@ -190,7 +190,7 @@ def incorrect_parenthesis_removal_begin(node) def safe_to_remove_line_containing_closing_paren?(node) last_line = processed_source[node.loc.end.line - 1] # Safe to remove if last line only contains `)`, `,`, and whitespace. - last_line.match?(/^[ ]*\)[ ]{0,20},{0,1}[ ]*$/) + last_line.match?(/^ *\) {0,20},{0,1} *$/) end def incorrect_parenthesis_removal_end(node) diff --git a/lib/rubocop/cop/migration/department_name.rb b/lib/rubocop/cop/migration/department_name.rb index 05356e350db..271edfebe47 100644 --- a/lib/rubocop/cop/migration/department_name.rb +++ b/lib/rubocop/cop/migration/department_name.rb @@ -24,7 +24,7 @@ def investigate(processed_source) offset = Regexp.last_match(1).length - Regexp.last_match(4).scan(/[^,]+|[\W]+/) do |name| + Regexp.last_match(4).scan(/[^,]+|\W+/) do |name| trimmed_name = name.strip unless valid_content_token?(trimmed_name) diff --git a/lib/rubocop/cop/mixin/uncommunicative_name.rb b/lib/rubocop/cop/mixin/uncommunicative_name.rb index 91030bcc21a..34f1b5c1c2c 100644 --- a/lib/rubocop/cop/mixin/uncommunicative_name.rb +++ b/lib/rubocop/cop/mixin/uncommunicative_name.rb @@ -18,7 +18,7 @@ def check(node, args) full_name = arg.children.first.to_s next if full_name == '_' - name = full_name.gsub(/\A([_]+)/, '') + name = full_name.gsub(/\A(_+)/, '') next if (arg.restarg_type? || arg.kwrestarg_type?) && name.empty? next if allowed_names.include?(name) diff --git a/lib/rubocop/cop/style/redundant_regexp_character_class.rb b/lib/rubocop/cop/style/redundant_regexp_character_class.rb new file mode 100644 index 00000000000..24935d7de94 --- /dev/null +++ b/lib/rubocop/cop/style/redundant_regexp_character_class.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Style + # This cop checks for unnecessary single-element Regexp character classes. + # + # @example + # + # # bad + # r = /[x]/ + # + # # good + # r = /x/ + # + # # bad + # r = /[\s]/ + # + # # good + # r = /\s/ + # + # # good + # r = /[ab]/ + class RedundantRegexpCharacterClass < Cop + include MatchRange + include RegexpLiteralHelp + + MSG_REDUNDANT_CHARACTER_CLASS = 'Redundant single-element character class, ' \ + '`%s` can be replaced with `%s`.' + + PATTERN = / + ( + (?