diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 31e62e461264..afd5fb3c7afe 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -38,7 +38,7 @@ output by `rubocop -V`, include them as well. Here's an example: ``` $ [bundle exec] rubocop -V -1.18.4 (using Parser 2.7.2.0, rubocop-ast 1.1.1, running on ruby 2.7.2 x86_64-linux) +1.19.0 (using Parser 2.7.2.0, rubocop-ast 1.1.1, running on ruby 2.7.2 x86_64-linux) - rubocop-performance 1.9.1 - rubocop-rspec 2.0.0 ``` diff --git a/CHANGELOG.md b/CHANGELOG.md index 509372533cb8..04ef8e7d7f86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +## 1.19.0 (2021-08-12) + ### New features * [#4182](https://github.com/rubocop/rubocop/issues/4182): Add `Lint/AmbiguousRange` cop to check for ranges with ambiguous boundaries. ([@dvandersluis][]) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6ba98723c889..0a4b7996937f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,7 @@ do so. ``` $ rubocop -V -1.18.4 (using Parser 2.7.2.0, rubocop-ast 1.1.1, running on ruby 2.7.2 x86_64-linux) +1.19.0 (using Parser 2.7.2.0, rubocop-ast 1.1.1, running on ruby 2.7.2 x86_64-linux) - rubocop-performance 1.9.1 - rubocop-rspec 2.0.0 ``` diff --git a/README.md b/README.md index 77b42106768a..555dfe6d6013 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi in your `Gemfile`: ```rb -gem 'rubocop', '~> 1.18', require: false +gem 'rubocop', '~> 1.19', require: false ``` See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details. diff --git a/config/default.yml b/config/default.yml index 0963ae99322b..53e201581c43 100644 --- a/config/default.yml +++ b/config/default.yml @@ -1437,7 +1437,7 @@ Lint/AmbiguousOperator: Lint/AmbiguousRange: Description: Checks for ranges with ambiguous boundaries. Enabled: pending - VersionAdded: '<>' + VersionAdded: '1.19' SafeAutoCorrect: false RequireParenthesesForMethodChains: false @@ -3164,7 +3164,7 @@ Style/CommentedKeyword: Enabled: true SafeAutoCorrect: false VersionAdded: '0.51' - VersionChanged: '<>' + VersionChanged: '1.19' Style/ConditionalAssignment: Description: >- @@ -3613,7 +3613,7 @@ Style/IdenticalConditionalBranches: Enabled: true SafeAutoCorrect: false VersionAdded: '0.36' - VersionChanged: '<>' + VersionChanged: '1.19' Style/IfInsideElse: Description: 'Finds if nodes inside else, which can be converted to elsif.' @@ -4418,7 +4418,7 @@ Style/RedundantSelfAssignment: Style/RedundantSelfAssignmentBranch: Description: 'Checks for places where conditional branch makes redundant self-assignment.' Enabled: pending - VersionAdded: '<>' + VersionAdded: '1.19' Style/RedundantSort: Description: >- @@ -4936,7 +4936,7 @@ Style/WordArray: StyleGuide: '#percent-w' Enabled: true VersionAdded: '0.9' - VersionChanged: '<>' + VersionChanged: '1.19' EnforcedStyle: percent SupportedStyles: # percent style: %w(word1 word2) diff --git a/docs/antora.yml b/docs/antora.yml index 52f2c59156f5..e54dcfd4464a 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -2,6 +2,6 @@ name: rubocop title: RuboCop # We always provide version without patch here (e.g. 1.1), # as patch versions should not appear in the docs. -version: 'master' +version: '1.19' nav: - modules/ROOT/nav.adoc diff --git a/docs/modules/ROOT/pages/cops.adoc b/docs/modules/ROOT/pages/cops.adoc index 057597a2b832..fad0414daf30 100644 --- a/docs/modules/ROOT/pages/cops.adoc +++ b/docs/modules/ROOT/pages/cops.adoc @@ -191,6 +191,7 @@ In the following section you find all available cops: * xref:cops_lint.adoc#lintambiguousassignment[Lint/AmbiguousAssignment] * xref:cops_lint.adoc#lintambiguousblockassociation[Lint/AmbiguousBlockAssociation] * xref:cops_lint.adoc#lintambiguousoperator[Lint/AmbiguousOperator] +* xref:cops_lint.adoc#lintambiguousrange[Lint/AmbiguousRange] * xref:cops_lint.adoc#lintambiguousregexpliteral[Lint/AmbiguousRegexpLiteral] * xref:cops_lint.adoc#lintassignmentincondition[Lint/AssignmentInCondition] * xref:cops_lint.adoc#lintbigdecimalnew[Lint/BigDecimalNew] @@ -516,6 +517,7 @@ In the following section you find all available cops: * xref:cops_style.adoc#styleredundantreturn[Style/RedundantReturn] * xref:cops_style.adoc#styleredundantself[Style/RedundantSelf] * xref:cops_style.adoc#styleredundantselfassignment[Style/RedundantSelfAssignment] +* xref:cops_style.adoc#styleredundantselfassignmentbranch[Style/RedundantSelfAssignmentBranch] * xref:cops_style.adoc#styleredundantsort[Style/RedundantSort] * xref:cops_style.adoc#styleredundantsortby[Style/RedundantSortBy] * xref:cops_style.adoc#styleregexpliteral[Style/RegexpLiteral] diff --git a/docs/modules/ROOT/pages/cops_layout.adoc b/docs/modules/ROOT/pages/cops_layout.adoc index c53ce58eaec5..e6c14433e84b 100644 --- a/docs/modules/ROOT/pages/cops_layout.adoc +++ b/docs/modules/ROOT/pages/cops_layout.adoc @@ -3936,8 +3936,7 @@ first part. There are some exceptions, such as implicit return values, where the concatenated string parts shall be indented regardless of `EnforcedStyle` configuration. If `EnforcedStyle: indented` is set, it's the second line that shall be indented one step -more than the first line. Lines 3 and forward shall be aligned with line 2. Here too there -are exceptions. Values in a hash literal are always aligned. +more than the first line. Lines 3 and forward shall be aligned with line 2. === Examples @@ -3961,11 +3960,6 @@ def some_method 'y' \ 'z' end - -my_hash = { - first: 'a message' \ - 'in two parts' -} ---- ==== EnforcedStyle: aligned (default) @@ -3976,9 +3970,19 @@ my_hash = { puts 'x' \ 'y' +my_hash = { + first: 'a message' \ + 'in two parts' +} + # good puts 'x' \ 'y' + +my_hash = { + first: 'a message' \ + 'in two parts' +} ---- ==== EnforcedStyle: indented @@ -3989,9 +3993,19 @@ puts 'x' \ result = 'x' \ 'y' +my_hash = { + first: 'a message' \ + 'in two parts' +} + # good result = 'x' \ 'y' + +my_hash = { + first: 'a message' \ + 'in two parts' +} ---- === Configurable attributes diff --git a/docs/modules/ROOT/pages/cops_lint.adoc b/docs/modules/ROOT/pages/cops_lint.adoc index 2c0ec8718918..1c7c9d55d89e 100644 --- a/docs/modules/ROOT/pages/cops_lint.adoc +++ b/docs/modules/ROOT/pages/cops_lint.adoc @@ -133,6 +133,93 @@ do_something(*some_array) * https://rubystyle.guide#method-invocation-parens +== Lint/AmbiguousRange + +|=== +| Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged + +| Pending +| Yes +| Yes (Unsafe) +| 1.19 +| - +|=== + +This cop checks for ambiguous ranges. + +Ranges have quite low precedence, which leads to unexpected behaviour when +using a range with other operators. This cop avoids that by making ranges +explicit by requiring parenthesis around complex range boundaries (anything +that is not a basic literal: numerics, strings, symbols, etc.). + +NOTE: The cop auto-corrects by wrapping the entire boundary in parentheses, which +makes the outcome more explicit but is possible to not be the intention of the +programmer. For this reason, this cop's auto-correct is marked as unsafe (it +will not change the behaviour of the code, but will not necessarily match the +intent of the program). + +This cop can be configured with `RequireParenthesesForMethodChains` in order to +specify whether method chains (including `self.foo`) should be wrapped in parens +by this cop. + +NOTE: Regardless of this configuration, if a method receiver is a basic literal +value, it will be wrapped in order to prevent the ambiguity of `1..2.to_a`. + +=== Examples + +[source,ruby] +---- +# bad +x || 1..2 +(x || 1..2) +1..2.to_a + +# good, unambiguous +1..2 +'a'..'z' +:bar..:baz +MyClass::MIN..MyClass::MAX +@min..@max +a..b +-a..b + +# good, ambiguity removed +x || (1..2) +(x || 1)..2 +(x || 1)..(y || 2) +(1..2).to_a +---- + +==== RequireParenthesesForMethodChains: false (default) + +[source,ruby] +---- +# good +a.foo..b.bar +(a.foo)..(b.bar) +---- + +==== RequireParenthesesForMethodChains: true + +[source,ruby] +---- +# bad +a.foo..b.bar + +# good +(a.foo)..(b.bar) +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| RequireParenthesesForMethodChains +| `false` +| Boolean +|=== + == Lint/AmbiguousRegexpLiteral |=== @@ -2899,16 +2986,6 @@ x < y && y < z 10 <= x && x <= 20 ---- -=== Configurable attributes - -|=== -| Name | Default value | Configurable values - -| AllowMethodComparison -| `true` -| Boolean -|=== - == Lint/NestedMethodDefinition |=== diff --git a/docs/modules/ROOT/pages/cops_naming.adoc b/docs/modules/ROOT/pages/cops_naming.adoc index 014ba08c2b0e..bc93d337d877 100644 --- a/docs/modules/ROOT/pages/cops_naming.adoc +++ b/docs/modules/ROOT/pages/cops_naming.adoc @@ -537,6 +537,8 @@ Flagged terms are configurable for the cop. For each flagged term an optional Regex can be specified to identify offenses. Suggestions for replacing a flagged term can be configured and will be displayed as part of the offense message. An AllowedRegex can be specified for a flagged term to exempt allowed uses of the term. +`WholeWord: true` can be set on a flagged term to indicate the cop should only match when +a term matches the whole word (partial matches will not be offenses). === Examples @@ -592,6 +594,19 @@ allow_list = %w(user1 user2) # They had a master's degree ---- +==== FlaggedTerms: { slave: { WholeWord: true } } + +[source,ruby] +---- +# Specify that only terms that are full matches will be flagged. + +# bad +Slave + +# good (won't be flagged despite containing `slave`) +TeslaVehicle +---- + === Configurable attributes |=== @@ -626,7 +641,7 @@ allow_list = %w(user1 user2) | Boolean | FlaggedTerms -| `{"whitelist"=>{"Regex"=>/white[-_\s]?list/, "Suggestions"=>["allowlist", "permit"]}, "blacklist"=>{"Regex"=>/black[-_\s]?list/, "Suggestions"=>["denylist", "block"]}, "slave"=>{"Suggestions"=>["replica", "secondary", "follower"]}}` +| `{"whitelist"=>{"Regex"=>/white[-_\s]?list/, "Suggestions"=>["allowlist", "permit"]}, "blacklist"=>{"Regex"=>/black[-_\s]?list/, "Suggestions"=>["denylist", "block"]}, "slave"=>{"WholeWord"=>true, "Suggestions"=>["replica", "secondary", "follower"]}}` | |=== diff --git a/docs/modules/ROOT/pages/cops_style.adoc b/docs/modules/ROOT/pages/cops_style.adoc index 591a92927372..20e8e386a54c 100644 --- a/docs/modules/ROOT/pages/cops_style.adoc +++ b/docs/modules/ROOT/pages/cops_style.adoc @@ -700,6 +700,11 @@ of comments... Check for uses of braces or do/end around single line or multi-line blocks. +Methods that can be either procedural or functional and cannot be +categorised from their usage alone is ignored. +`lambda`, `proc`, and `it` are their defaults. +Additional methods can be added to the `IgnoredMethods`. + === Examples ==== EnforcedStyle: line_count_based (default) @@ -847,6 +852,20 @@ def bar(foo) end ---- +==== IgnoredMethods: ['lambda', 'proc', 'it' ] (default) + +[source,ruby] +---- +# good +foo = lambda do |x| + puts "Hello, #{x}" +end + +foo = lambda do |x| + x * 100 +end +---- + === Configurable attributes |=== @@ -1832,9 +1851,9 @@ annotation. | Enabled | Yes -| Yes +| Yes (Unsafe) | 0.51 -| 1.7 +| 1.19 |=== This cop checks for comments put on the same line as some keywords. @@ -1846,6 +1865,7 @@ are allowed. Auto-correction removes comments from `end` keyword and keeps comments for `class`, `module`, `def` and `begin` above the keyword. +It is marked as unsafe auto-correction as it may remove meaningful comments. === Examples @@ -4613,8 +4633,6 @@ syntax hashes == Style/HashTransformKeys -NOTE: Required Ruby version: 2.5 - |=== | Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged @@ -4698,15 +4716,31 @@ Hash[{a: 1, b: 2}.collect { |k, v| [k, foo(v)] }] | Enabled | Yes -| Yes +| Yes (Unsafe) | 0.36 -| 1.16 +| 1.19 |=== This cop checks for identical expressions at the beginning or end of each branch of a conditional expression. Such expressions should normally be placed outside the conditional expression - before or after it. +This cop is marked unsafe auto-correction as the order of method invocations +must be guaranteed in the following case: + +[source,ruby] +---- +if method_that_modifies_global_state # 1 + method_that_relies_on_global_state # 2 + foo # 3 +else + method_that_relies_on_global_state # 2 + bar # 3 +end +---- + +In such a case, auto-correction may change the invocation order. + NOTE: The cop is poorly named and some people might think that it actually checks for duplicated conditional branches. The name will probably be changed in a future major RuboCop release. @@ -6032,6 +6066,9 @@ return foo.minmax Checks for `if` expressions that do not have an `else` branch. +NOTE: Pattern matching is allowed to have no `else` branch because unlike `if` and `case`, +it raises `NoMatchingPatternError` if the pattern doesn't match and without having `else`. + Supported styles are: if, case, both. === Examples @@ -6808,6 +6845,16 @@ foo if a == b.lightweight || a == b.heavyweight foo if [b.lightweight, b.heavyweight].include?(a) ---- +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| AllowMethodComparison +| `true` +| Boolean +|=== + == Style/MutableConstant |=== @@ -7873,6 +7920,10 @@ end | SuspiciousParamNames | `options`, `opts`, `args`, `params`, `parameters` | Array + +| Allowlist +| `[]` +| Array |=== == Style/OptionalArguments @@ -9379,6 +9430,37 @@ foo.concat(ary) self.foo += ary ---- +== Style/RedundantSelfAssignmentBranch + +|=== +| Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged + +| Pending +| Yes +| Yes +| 1.19 +| - +|=== + +This cop checks for places where conditional branch makes redundant self-assignment. + +=== Examples + +[source,ruby] +---- +# bad +foo = condition ? bar : foo + +# good +foo = bar if condition + +# bad +foo = condition ? foo : bar + +# good +foo = bar unless condition +---- + == Style/RedundantSort |=== @@ -10475,6 +10557,9 @@ end |=== This cop looks for uses of Perl-style global variables. +Correcting to global variables in the 'English' library +will add a require statement to the top of the file if +enabled by RequireEnglish config. === Examples @@ -10483,6 +10568,8 @@ This cop looks for uses of Perl-style global variables. [source,ruby] ---- # good +require 'English' # or this could be in another file. + puts $LOAD_PATH puts $LOADED_FEATURES puts $PROGRAM_NAME @@ -10533,6 +10620,10 @@ puts $* |=== | Name | Default value | Configurable values +| RequireEnglish +| `true` +| Boolean + | EnforcedStyle | `use_english_names` | `use_perl_names`, `use_english_names` @@ -12380,7 +12471,7 @@ end === References -* https://rubystyle.guide#one-line-cases +* https://rubystyle.guide#no-when-semicolons == Style/WhileUntilDo @@ -12492,7 +12583,7 @@ end | Yes | Yes | 0.9 -| 0.36 +| 1.19 |=== This cop can check for array literals made up of word-like @@ -12501,6 +12592,9 @@ strings, that are not using the %w() syntax. Alternatively, it can check for uses of the %w() syntax, in projects which do not want to include that syntax. +NOTE: When using the `percent` style, %w() arrays containing a space +will be registered as offenses. + Configuration option: MinSize If set, arrays with fewer elements than this value will not trigger the cop. For example, a `MinSize` of `3` will not enforce a style on an @@ -12517,6 +12611,9 @@ array of 2 or fewer elements. # bad ['foo', 'bar', 'baz'] + +# bad (contains spaces) +%w[foo\ bar baz\ quux] ---- ==== EnforcedStyle: brackets @@ -12528,6 +12625,9 @@ array of 2 or fewer elements. # bad %w[foo bar baz] + +# good (contains spaces) +['foo bar', 'baz quux'] ---- === Configurable attributes diff --git a/docs/modules/ROOT/pages/installation.adoc b/docs/modules/ROOT/pages/installation.adoc index 01a1492de226..407e3bcd0647 100644 --- a/docs/modules/ROOT/pages/installation.adoc +++ b/docs/modules/ROOT/pages/installation.adoc @@ -22,7 +22,7 @@ in your `Gemfile`: [source,rb] ---- -gem 'rubocop', '~> 1.18', require: false +gem 'rubocop', '~> 1.19', require: false ---- NOTE: You can check out our progress on the road to version 1.0 https://github.com/rubocop/rubocop/milestone/4[here]. diff --git a/lib/rubocop/version.rb b/lib/rubocop/version.rb index 37fcb353174d..8522a14e9ecf 100644 --- a/lib/rubocop/version.rb +++ b/lib/rubocop/version.rb @@ -3,7 +3,7 @@ module RuboCop # This module holds the RuboCop version information. module Version - STRING = '1.18.4' + STRING = '1.19.0' MSG = '%s (using Parser %s, '\ 'rubocop-ast %s, ' \ diff --git a/relnotes/v1.19.0.md b/relnotes/v1.19.0.md new file mode 100644 index 000000000000..41e215b4b0e7 --- /dev/null +++ b/relnotes/v1.19.0.md @@ -0,0 +1,43 @@ +### New features + +* [#4182](https://github.com/rubocop/rubocop/issues/4182): Add `Lint/AmbiguousRange` cop to check for ranges with ambiguous boundaries. ([@dvandersluis][]) +* [#10000](https://github.com/rubocop/rubocop/pull/10000): Parallel static analysis by default. ([@koic][]) +* [#9948](https://github.com/rubocop/rubocop/pull/9948): Support Ruby 2.7's pattern matching for `Style/ConditionalAssignment` cop. ([@koic][]) +* [#9999](https://github.com/rubocop/rubocop/pull/9999): Add new `Style/RedundantSelfAssignmentBranch` cop. ([@koic][]) + +### Bug fixes + +* [#9927](https://github.com/rubocop/rubocop/issues/9927): Indent hash values in `Layout/LineEndStringConcatenationIndentation`. ([@jonas054][]) +* [#9959](https://github.com/rubocop/rubocop/issues/9959): Make `Style/IdenticalConditionalBranches` able to handle ternary `if`s. ([@dvandersluis][]) +* [#9946](https://github.com/rubocop/rubocop/issues/9946): Avoid slow regexp matches in `Style/CommentedKeyword`. ([@jonas054][]) +* [#7422](https://github.com/rubocop/rubocop/issues/7422): Treat constant assignment like other assignment in `Layout/SpaceAroundOperators`. ([@dvandersluis][]) +* [#9953](https://github.com/rubocop/rubocop/issues/9953): Fix an infinite loop error and a false auto-correction behavior for `Layout/EndAlignment` when using a conditional statement in a method argument. ([@koic][]) +* [#9958](https://github.com/rubocop/rubocop/issues/9958): Prevent an infinite loop when a detected method has fewer arguments than expected. ([@dvandersluis][]) +* [#9977](https://github.com/rubocop/rubocop/issues/9977): Update `Layout/EmptyLineAfterGuardClause` to not register an offense if there is another expression following the guard clause on the same line. ([@dvandersluis][]) +* [#9980](https://github.com/rubocop/rubocop/issues/9980): Fix a false positive for `Style/IdenticalConditionalBranches` when assigning to a variable used in a condition. ([@koic][]) +* [#9975](https://github.com/rubocop/rubocop/issues/9975): Parentheses are always required for `Style/MethodDefParentheses` when a forwarding argument (`...`) is used. ([@dvandersluis][]) +* [#9984](https://github.com/rubocop/rubocop/pull/9984): Fix false negatives involving heredocs for `Layout/SpaceBeforeComma`, `Layout/SpaceBeforeComment`, `Layout/SpaceBeforeSemicolon` and `Layout/SpaceInsideParens`. ([@dvandersluis][]) +* [#9954](https://github.com/rubocop/rubocop/issues/9954): Fix infinite loop error for `Layout/HashAlignment` when `EnforcedStyle: with_fixed_indentation` is specified for `Layout/ArgumentAlignment`. ([@koic][]) +* [#10002](https://github.com/rubocop/rubocop/issues/10002): Fix an incorrect auto-correct for `Lint/AmbigousRegexpLiteral` when using nested method arguments without parentheses. ([@koic][]) +* [#9952](https://github.com/rubocop/rubocop/pull/9952) [rubocop-rspec#1126](https://github.com/rubocop/rubocop-rspec/issues/1126): Fix `inherit_mode` for deeply nested configuration defined in extensions' default configuration. ([@pirj][]) +* [#9957](https://github.com/rubocop/rubocop/issues/9957): Add `WholeWord` configuration to `Naming/InclusiveLanguage`'s `FlaggedTerms` config. ([@dvandersluis][]) +* [#9970](https://github.com/rubocop/rubocop/pull/9970): Don't register an offense when sort method has arguments for `Style/RedundantSort` cop. ([@mtsmfm][]) +* [#4097](https://github.com/rubocop/rubocop/issues/4097): Add require English for special globals. ([@biinari][]) +* [#9955](https://github.com/rubocop/rubocop/issues/9955): Fix `Style/ExplicitBlockArgument` adding a second set of parentheses. ([@dvandersluis][]) +* [#9973](https://github.com/rubocop/rubocop/issues/9973): Fix a false positive for `Layout/RescueEnsureAlignment` when aligned `rescue` keyword and leading dot. ([@koic][]) +* [#9945](https://github.com/rubocop/rubocop/issues/9945): Fix auto-correction of lines in heredocs with only spaces in `Layout/TrailingWhitespace`. ([@jonas054][]) + +### Changes + +* [#9989](https://github.com/rubocop/rubocop/issues/9989): Mark `Style/CommentedKeyword` as unsafe auto-correction. ([@koic][]) +* [#9964](https://github.com/rubocop/rubocop/pull/9964): Make `Layout/LeadingCommentSpace` aware of `#:nodoc`. ([@koic][]) +* [#9985](https://github.com/rubocop/rubocop/pull/9985): Mark `Style/IdenticalConditionalBranches` as unsafe auto-correction. ([@koic][]) +* [#9962](https://github.com/rubocop/rubocop/issues/9962): Update `Style/WordArray` to register an offense in `percent` style if any values contain spaces. ([@dvandersluis][]) +* [#9979](https://github.com/rubocop/rubocop/pull/9979): Enable basic autocorrection for `Style/Semicolon`. ([@dvandersluis][]) + +[@dvandersluis]: https://github.com/dvandersluis +[@koic]: https://github.com/koic +[@jonas054]: https://github.com/jonas054 +[@pirj]: https://github.com/pirj +[@mtsmfm]: https://github.com/mtsmfm +[@biinari]: https://github.com/biinari