From 9b836ddbfec0f9e7375752a56d8452ea4e8efe43 Mon Sep 17 00:00:00 2001 From: David Marinho Date: Wed, 8 Nov 2023 14:52:04 +0000 Subject: [PATCH] bump rubocop 1.57.2 --- Gemfile | 2 +- Gemfile.lock | 61 ++++--- .../Layout_EmptyLineAfterGuardClause.md | 18 +- docs/description/Lint_EmptyBlock.md | 2 +- .../Lint_RedundantSafeNavigation.md | 14 +- docs/description/Lint_UselessAssignment.md | 8 +- docs/description/Lint_Void.md | 10 ++ docs/description/Metrics_BlockLength.md | 3 +- docs/description/Performance_RangeInclude.md | 5 - .../Rails_ActionControllerTestCase.md | 4 +- docs/description/Rails_ActionFilter.md | 3 + docs/description/Rails_BulkChangeTable.md | 5 +- .../description/Rails_DangerousColumnNames.md | 16 ++ .../description/Rails_DuplicateAssociation.md | 9 + docs/description/Rails_EnvLocal.md | 16 ++ .../Rails_HelperInstanceVariable.md | 2 +- docs/description/Rails_HttpStatus.md | 1 + docs/description/Rails_I18nLazyLookup.md | 20 +++ docs/description/Rails_NotNullColumn.md | 9 +- .../Rails_RedundantActiveRecordAllMethod.md | 22 +++ docs/description/Rails_SelectMap.md | 17 ++ docs/description/Rails_TimeZone.md | 1 + .../Rails_TransactionExitStatement.md | 5 + docs/description/Rails_UnusedRenderContent.md | 19 ++ docs/description/Rails_WhereExists.md | 1 - .../Sorbet_BuggyObsoleteStrictMemoization.md | 34 ++++ docs/description/Sorbet_EmptyLineAfterSig.md | 3 - docs/description/Sorbet_ForbidTStruct.md | 36 ++++ .../description/Sorbet_SignatureBuildOrder.md | 21 +++ docs/description/Style_ArrayIntersect.md | 9 + docs/description/Style_CollectionMethods.md | 2 + docs/description/Style_FormatString.md | 16 +- docs/description/Style_GuardClause.md | 21 ++- .../Style_RedundantDoubleSplatHashBraces.md | 6 + docs/description/Style_RedundantException.md | 15 +- .../description/Style_RedundantFilterChain.md | 11 +- docs/description/Style_ReturnNil.md | 8 +- .../description/Style_SingleLineDoEndBlock.md | 27 +++ docs/description/Style_YodaExpression.md | 13 +- docs/description/description.json | 148 ++++++++++++++-- docs/patterns.json | 165 ++++++++++++++++-- 41 files changed, 715 insertions(+), 93 deletions(-) create mode 100644 docs/description/Rails_DangerousColumnNames.md create mode 100644 docs/description/Rails_EnvLocal.md create mode 100644 docs/description/Rails_RedundantActiveRecordAllMethod.md create mode 100644 docs/description/Rails_SelectMap.md create mode 100644 docs/description/Rails_UnusedRenderContent.md create mode 100644 docs/description/Sorbet_BuggyObsoleteStrictMemoization.md create mode 100644 docs/description/Sorbet_ForbidTStruct.md create mode 100644 docs/description/Style_SingleLineDoEndBlock.md diff --git a/Gemfile b/Gemfile index 498b302b..3422b20d 100644 --- a/Gemfile +++ b/Gemfile @@ -14,7 +14,7 @@ gem "pry" gem "safe_yaml" gem "dark_finger" gem "rubocop-migrations" -gem "rubocop", "1.56.1" +gem "rubocop", "1.57.2" #Needed to be referenced on some user configs gem "graphql" #Rubocop official modules diff --git a/Gemfile.lock b/Gemfile.lock index 934731c8..69706fd9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,88 +1,99 @@ GEM remote: https://rubygems.org/ specs: - activesupport (7.0.7.2) + activesupport (7.1.1) + base64 + bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) minitest (>= 5.1) + mutex_m tzinfo (~> 2.0) ast (2.4.2) - base64 (0.1.1) + base64 (0.2.0) + bigdecimal (3.1.4) coderay (1.1.3) concurrent-ruby (1.2.2) + connection_pool (2.4.1) dark_finger (0.6.1) rubocop (>= 0.51.0) - graphql (2.1.0) + drb (2.2.0) + ruby2_keywords + graphql (2.1.6) + racc (~> 1.4) i18n (1.14.1) concurrent-ruby (~> 1.0) json (2.6.3) language_server-protocol (3.17.0.3) method_source (1.0.0) - minitest (5.19.0) + minitest (5.20.0) + mutex_m (0.2.0) parallel (1.23.0) - parser (3.2.2.3) + parser (3.2.2.4) ast (~> 2.4.1) racc pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) - psych (4.0.6) + psych (5.1.1.1) stringio - racc (1.7.1) + racc (1.7.3) rack (3.0.8) rainbow (3.1.1) - rake (13.0.6) - rdoc (6.5.0) + rake (13.1.0) + rdoc (6.6.0) psych (>= 4.0.0) - regexp_parser (2.8.1) + regexp_parser (2.8.2) rexml (3.2.6) - rubocop (1.56.1) - base64 (~> 0.1.1) + rubocop (1.57.2) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 3.2.2.3) + parser (>= 3.2.2.4) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) rubocop-ast (>= 1.28.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.29.0) + rubocop-ast (1.30.0) parser (>= 3.2.1.0) - rubocop-capybara (2.18.0) + rubocop-capybara (2.19.0) rubocop (~> 1.41) - rubocop-factory_bot (2.23.1) + rubocop-factory_bot (2.24.0) rubocop (~> 1.33) rubocop-graphql (1.4.0) rubocop (>= 0.90, < 2) rubocop-migrations (0.1.0) rubocop (>= 0.42.0) - rubocop-performance (1.19.0) + rubocop-performance (1.19.1) rubocop (>= 1.7.0, < 2.0) rubocop-ast (>= 0.4.0) - rubocop-rails (2.20.2) + rubocop-rails (2.22.1) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.33.0, < 2.0) rubocop-rake (0.6.0) rubocop (~> 1.0) - rubocop-rspec (2.23.2) - rubocop (~> 1.33) + rubocop-rspec (2.25.0) + rubocop (~> 1.40) rubocop-capybara (~> 2.17) rubocop-factory_bot (~> 2.22) rubocop-shopify (2.14.0) rubocop (~> 1.51) - rubocop-sorbet (0.7.3) + rubocop-sorbet (0.7.5) rubocop (>= 0.90.0) rubocop-thread_safety (0.5.1) rubocop (>= 0.90.0) ruby-progressbar (1.13.0) + ruby2_keywords (0.0.5) safe_yaml (1.0.5) - stringio (3.0.8) + stringio (3.0.9) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (2.4.2) + unicode-display_width (2.5.0) yard (0.9.34) PLATFORMS @@ -96,7 +107,7 @@ DEPENDENCIES pry rake rdoc - rubocop (= 1.56.1) + rubocop (= 1.57.2) rubocop-graphql rubocop-migrations rubocop-performance @@ -110,4 +121,4 @@ DEPENDENCIES yard BUNDLED WITH - 2.4.19 + 2.4.17 diff --git a/docs/description/Layout_EmptyLineAfterGuardClause.md b/docs/description/Layout_EmptyLineAfterGuardClause.md index 9af8126a..2760b817 100644 --- a/docs/description/Layout_EmptyLineAfterGuardClause.md +++ b/docs/description/Layout_EmptyLineAfterGuardClause.md @@ -1,5 +1,21 @@ -Enforces empty line after guard clause +Enforces empty line after guard clause. + +This cop allows `# :nocov:` directive after guard clause because +SimpleCov excludes code from the coverage report by wrapping it in `# :nocov:`: + +[source,ruby] +---- +def foo + # :nocov: + return if condition + # :nocov: + bar +end +---- + +Refer to SimpleCov's documentation for more details: +https://github.com/simplecov-ruby/simplecov#ignoringskipping-code # Examples diff --git a/docs/description/Lint_EmptyBlock.md b/docs/description/Lint_EmptyBlock.md index 2335de12..d2278414 100644 --- a/docs/description/Lint_EmptyBlock.md +++ b/docs/description/Lint_EmptyBlock.md @@ -1,7 +1,7 @@ Checks for blocks without a body. Such empty blocks are typically an oversight or we should provide a comment -be clearer what we're aiming for. +to clarify what we're aiming for. Empty lambdas and procs are ignored by default. diff --git a/docs/description/Lint_RedundantSafeNavigation.md b/docs/description/Lint_RedundantSafeNavigation.md index f8bd217b..e8cf3fbc 100644 --- a/docs/description/Lint_RedundantSafeNavigation.md +++ b/docs/description/Lint_RedundantSafeNavigation.md @@ -1,7 +1,11 @@ Checks for redundant safe navigation calls. -`instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`, and `equal?` methods -are checked by default. These are customizable with `AllowedMethods` option. +Use cases where a constant, named in camel case for classes and modules is `nil` are rare, +and an offense is not detected when the receiver is a snake case constant. + +For all receivers, the `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`, +and `equal?` methods are checked by default. +These are customizable with `AllowedMethods` option. The `AllowedMethods` option specifies nil-safe methods, in other words, it is a method that is allowed to skip safe navigation. @@ -14,6 +18,9 @@ because `NilClass` has methods like `respond_to?` and `is_a?`. # Examples ```ruby +# bad +CamelCaseConst&.do_something + # bad do_something if attrs&.respond_to?(:[]) @@ -25,6 +32,9 @@ while node&.is_a?(BeginNode) node = node.parent end +# good +CamelCaseConst.do_something + # good while node.is_a?(BeginNode) node = node.parent diff --git a/docs/description/Lint_UselessAssignment.md b/docs/description/Lint_UselessAssignment.md index 3a35b9d7..bde8fffd 100644 --- a/docs/description/Lint_UselessAssignment.md +++ b/docs/description/Lint_UselessAssignment.md @@ -3,12 +3,18 @@ Checks for every useless assignment to local variable in every scope. The basic idea for this cop was from the warning of `ruby -cw`: - assigned but unused variable - foo +[source,console] +---- +assigned but unused variable - foo +---- Currently this cop has advanced logic that detects unreferenced reassignments and properly handles varied cases such as branch, loop, rescue, ensure, etc. +NOTE: Given the assignment `foo = 1, bar = 2`, removing unused variables +can lead to a syntax error, so this case is not autocorrected. + # Examples ```ruby diff --git a/docs/description/Lint_Void.md b/docs/description/Lint_Void.md index 3ffbdba6..619b818e 100644 --- a/docs/description/Lint_Void.md +++ b/docs/description/Lint_Void.md @@ -2,6 +2,16 @@ Checks for operators, variables, literals, lambda, proc and nonmutating methods used in void context. +`each` blocks are allowed to prevent false positives. +For example, the expression inside the `each` block below. +It's not void, especially when the receiver is an `Enumerator`: + +[source,ruby] +---- +enumerator = [1, 2, 3].filter +enumerator.each { |item| item >= 2 } #=> [2, 3] +---- + # Examples ```ruby diff --git a/docs/description/Metrics_BlockLength.md b/docs/description/Metrics_BlockLength.md index e78a1217..29862d6a 100644 --- a/docs/description/Metrics_BlockLength.md +++ b/docs/description/Metrics_BlockLength.md @@ -8,13 +8,12 @@ You can set constructs you want to fold with `CountAsOne`. Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct will be counted as one line regardless of its actual size. +NOTE: This cop does not apply for `Struct` definitions. NOTE: The `ExcludedMethods` configuration is deprecated and only kept for backwards compatibility. Please use `AllowedMethods` and `AllowedPatterns` instead. By default, there are no methods to allowed. -NOTE: This cop does not apply for `Struct` definitions. - # Examples ```ruby diff --git a/docs/description/Performance_RangeInclude.md b/docs/description/Performance_RangeInclude.md index 0c3be2c5..e47d6547 100644 --- a/docs/description/Performance_RangeInclude.md +++ b/docs/description/Performance_RangeInclude.md @@ -14,11 +14,6 @@ is wanted. # good ('a'..'z').cover?('b') # => true - -# Example of a case where `Range#cover?` may not provide -# the desired result: - -('a'..'z').cover?('yellow') # => true ``` [Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Performance/RangeInclude) \ No newline at end of file diff --git a/docs/description/Rails_ActionControllerTestCase.md b/docs/description/Rails_ActionControllerTestCase.md index b06d7b1e..1ef21704 100644 --- a/docs/description/Rails_ActionControllerTestCase.md +++ b/docs/description/Rails_ActionControllerTestCase.md @@ -1,6 +1,6 @@ -Using `ActionController::TestCase`` is discouraged and should be replaced by -`ActionDispatch::IntegrationTest``. Controller tests are too close to the +Using `ActionController::TestCase` is discouraged and should be replaced by +`ActionDispatch::IntegrationTest`. Controller tests are too close to the internals of a controller whereas integration tests mimic the browser/user. # Examples diff --git a/docs/description/Rails_ActionFilter.md b/docs/description/Rails_ActionFilter.md index 0b8b6e2b..54449276 100644 --- a/docs/description/Rails_ActionFilter.md +++ b/docs/description/Rails_ActionFilter.md @@ -4,6 +4,9 @@ Enforces the consistent use of action filter methods. The cop is configurable and can enforce the use of the older something_filter methods or the newer something_action methods. +IMPORTANT: This cop is deprecated. Because the `*_filter` methods were removed in Rails 4.2, +and that Rails version is no longer supported by RuboCop Rails. This cop will be removed in RuboCop Rails 3.0. + # Examples ```ruby diff --git a/docs/description/Rails_BulkChangeTable.md b/docs/description/Rails_BulkChangeTable.md index 86ba194b..5dd5f5e1 100644 --- a/docs/description/Rails_BulkChangeTable.md +++ b/docs/description/Rails_BulkChangeTable.md @@ -8,8 +8,9 @@ ALTER TABLE statement combining multiple column alterations. The `bulk` option is only supported on the MySQL and the PostgreSQL (5.2 later) adapter; thus it will automatically detect an adapter from `development` environment -in `config/database.yml` when the `Database` option is not set. -If the adapter is not `mysql2` or `postgresql`, +in `config/database.yml` or the environment variable `DATABASE_URL` +when the `Database` option is not set. +If the adapter is not `mysql2`, `trilogy`, or `postgresql`, this Cop ignores offenses. # Examples diff --git a/docs/description/Rails_DangerousColumnNames.md b/docs/description/Rails_DangerousColumnNames.md new file mode 100644 index 00000000..671776dc --- /dev/null +++ b/docs/description/Rails_DangerousColumnNames.md @@ -0,0 +1,16 @@ + +Avoid dangerous column names. + +Some column names are considered dangerous because they would overwrite methods already defined. + +# Examples + +```ruby +# bad +add_column :users, :save + +# good +add_column :users, :saved +``` + +[Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/DangerousColumnNames) \ No newline at end of file diff --git a/docs/description/Rails_DuplicateAssociation.md b/docs/description/Rails_DuplicateAssociation.md index a1c115df..63e45e9f 100644 --- a/docs/description/Rails_DuplicateAssociation.md +++ b/docs/description/Rails_DuplicateAssociation.md @@ -17,6 +17,15 @@ has_one :foo # good belongs_to :bar has_one :foo + +# bad +has_many :foo, class_name: 'Foo' +has_many :bar, class_name: 'Foo' +has_one :baz + +# good +has_many :bar, class_name: 'Foo' +has_one :foo ``` [Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/DuplicateAssociation) \ No newline at end of file diff --git a/docs/description/Rails_EnvLocal.md b/docs/description/Rails_EnvLocal.md new file mode 100644 index 00000000..642fe0dc --- /dev/null +++ b/docs/description/Rails_EnvLocal.md @@ -0,0 +1,16 @@ + +Checks for usage of `Rails.env.development? || Rails.env.test?` which +can be replaced with `Rails.env.local?`, introduced in Rails 7.1. + +# Examples + +```ruby + +# bad +Rails.env.development? || Rails.env.test? + +# good +Rails.env.local? +``` + +[Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/EnvLocal) \ No newline at end of file diff --git a/docs/description/Rails_HelperInstanceVariable.md b/docs/description/Rails_HelperInstanceVariable.md index fc1bc793..9dca1a35 100644 --- a/docs/description/Rails_HelperInstanceVariable.md +++ b/docs/description/Rails_HelperInstanceVariable.md @@ -2,7 +2,7 @@ Checks for use of the helper methods which reference instance variables. -Relying on instance variables makes it difficult to re-use helper +Relying on instance variables makes it difficult to reuse helper methods. If it seems awkward to explicitly pass in each dependent diff --git a/docs/description/Rails_HttpStatus.md b/docs/description/Rails_HttpStatus.md index cf6df8ea..1cb6dc04 100644 --- a/docs/description/Rails_HttpStatus.md +++ b/docs/description/Rails_HttpStatus.md @@ -6,6 +6,7 @@ Enforces use of symbolic or numeric value to define HTTP status. ```ruby # bad render :foo, status: 200 +render :foo, status: '200' render json: { foo: 'bar' }, status: 200 render plain: 'foo/bar', status: 304 redirect_to root_url, status: 301 diff --git a/docs/description/Rails_I18nLazyLookup.md b/docs/description/Rails_I18nLazyLookup.md index aa1cd969..cd35335c 100644 --- a/docs/description/Rails_I18nLazyLookup.md +++ b/docs/description/Rails_I18nLazyLookup.md @@ -1,6 +1,12 @@ Checks for places where I18n "lazy" lookup can be used. +This cop has two different enforcement modes. When the EnforcedStyle +is `lazy` (the default), explicit lookups are added as offenses. + +When the EnforcedStyle is `explicit` then lazy lookups are added as +offenses. + # Examples ```ruby @@ -24,6 +30,20 @@ class BooksController < ApplicationController # ... redirect_to books_url, notice: t('.success') end +end# bad +class BooksController < ApplicationController + def create + # ... + redirect_to books_url, notice: t('.success') + end +end + +# good +class BooksController < ApplicationController + def create + # ... + redirect_to books_url, notice: t('books.create.success') + end end ``` diff --git a/docs/description/Rails_NotNullColumn.md b/docs/description/Rails_NotNullColumn.md index a69be228..0d40d074 100644 --- a/docs/description/Rails_NotNullColumn.md +++ b/docs/description/Rails_NotNullColumn.md @@ -1,6 +1,11 @@ -Checks for add_column call with NOT NULL constraint -in migration file. +Checks for add_column call with NOT NULL constraint in migration file. + +`TEXT` can have default values in PostgreSQL, but not in MySQL. +It will automatically detect an adapter from `development` environment +in `config/database.yml` or the environment variable `DATABASE_URL` +when the `Database` option is not set. If the database is MySQL, +this cop ignores offenses for the `TEXT`. # Examples diff --git a/docs/description/Rails_RedundantActiveRecordAllMethod.md b/docs/description/Rails_RedundantActiveRecordAllMethod.md new file mode 100644 index 00000000..90fa2a1d --- /dev/null +++ b/docs/description/Rails_RedundantActiveRecordAllMethod.md @@ -0,0 +1,22 @@ + +Detect redundant `all` used as a receiver for Active Record query methods. + +# Examples + +```ruby +# bad +User.all.find(id) +User.all.order(:created_at) +users.all.where(id: ids) +user.articles.all.order(:created_at) + +# good +User.find(id) +User.order(:created_at) +users.where(id: ids) +user.articles.order(:created_at)# good +ActionMailer::Preview.all.first +ActiveSupport::TimeZone.all.first +``` + +[Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/RedundantActiveRecordAllMethod) \ No newline at end of file diff --git a/docs/description/Rails_SelectMap.md b/docs/description/Rails_SelectMap.md new file mode 100644 index 00000000..f28eaa5e --- /dev/null +++ b/docs/description/Rails_SelectMap.md @@ -0,0 +1,17 @@ + +Checks for uses of `select(:column_name)` with `map(&:column_name)`. +These can be replaced with `pluck(:column_name)`. + +There also should be some performance improvement since it skips instantiating the model class for matches. + +# Examples + +```ruby +# bad +Model.select(:column_name).map(&:column_name) + +# good +Model.pluck(:column_name) +``` + +[Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/SelectMap) \ No newline at end of file diff --git a/docs/description/Rails_TimeZone.md b/docs/description/Rails_TimeZone.md index 3c4c24cd..f3ed14b1 100644 --- a/docs/description/Rails_TimeZone.md +++ b/docs/description/Rails_TimeZone.md @@ -16,6 +16,7 @@ to use `Time#in_time_zone`. # bad Time.now Time.parse('2015-03-02T19:05:37') +'2015-03-02T19:05:37'.to_time # good Time.current diff --git a/docs/description/Rails_TransactionExitStatement.md b/docs/description/Rails_TransactionExitStatement.md index 479837a9..67b09e9f 100644 --- a/docs/description/Rails_TransactionExitStatement.md +++ b/docs/description/Rails_TransactionExitStatement.md @@ -9,6 +9,8 @@ As alternatives, it would be more intuitive to explicitly raise an error when rollback is desired, and to use `next` when commit is desired. +If you are defining custom transaction methods, you can configure it with `TransactionMethods`. + # Examples ```ruby @@ -47,6 +49,9 @@ end ApplicationRecord.transaction do # Commit next if user.active? +end# bad +CustomModel.custom_transaction do + return if user.active? end ``` diff --git a/docs/description/Rails_UnusedRenderContent.md b/docs/description/Rails_UnusedRenderContent.md new file mode 100644 index 00000000..3a5daf90 --- /dev/null +++ b/docs/description/Rails_UnusedRenderContent.md @@ -0,0 +1,19 @@ + +If you try to render content along with a non-content status code (100-199, 204, 205, or 304), +it will be dropped from the response. + +This cop checks for uses of `render` which specify both body content and a non-content status. + +# Examples + +```ruby +# bad +render 'foo', status: :continue +render status: 100, plain: 'Ruby!' + +# good +head :continue +head 100 +``` + +[Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/UnusedRenderContent) \ No newline at end of file diff --git a/docs/description/Rails_WhereExists.md b/docs/description/Rails_WhereExists.md index cf367751..3fa108bd 100644 --- a/docs/description/Rails_WhereExists.md +++ b/docs/description/Rails_WhereExists.md @@ -22,7 +22,6 @@ User.where('length(name) > 10').exists? user.posts.exists?(published: true)# bad User.exists?(name: 'john') User.exists?(['name = ?', 'john']) -User.exists?('name = ?', 'john') user.posts.exists?(published: true) # good diff --git a/docs/description/Sorbet_BuggyObsoleteStrictMemoization.md b/docs/description/Sorbet_BuggyObsoleteStrictMemoization.md new file mode 100644 index 00000000..4104b35f --- /dev/null +++ b/docs/description/Sorbet_BuggyObsoleteStrictMemoization.md @@ -0,0 +1,34 @@ + +Checks for the a mistaken variant of the "obsolete memoization pattern" that used to be required +for older Sorbet versions in `#typed: strict` files. The mistaken variant would overwrite the ivar with `nil` +on every call, causing the memoized value to be discarded and recomputed on every call. + +This cop will correct it to read from the ivar instead of `nil`, which will memoize it correctly. + +The result of this correction will be the "obsolete memoization pattern", which can further be corrected by +the `Sorbet/ObsoleteStrictMemoization` cop. + +See `Sorbet/ObsoleteStrictMemoization` for more details. + +# Examples + +```ruby +# bad +sig { returns(Foo) } +def foo + # This `nil` is likely a mistake, causing the memoized value to be discarded and recomputed on every call. + @foo = T.let(nil, T.nilable(Foo)) + @foo ||= some_computation +end + +# good +sig { returns(Foo) } +def foo + # This will now memoize the value as was likely intended, so `some_computation` is only ever called once. + # ⚠️If `some_computation` has side effects, this might be a breaking change! + @foo = T.let(@foo, T.nilable(Foo)) + @foo ||= some_computation +end +``` + +[Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Sorbet/BuggyObsoleteStrictMemoization) \ No newline at end of file diff --git a/docs/description/Sorbet_EmptyLineAfterSig.md b/docs/description/Sorbet_EmptyLineAfterSig.md index aaae104d..df711c00 100644 --- a/docs/description/Sorbet_EmptyLineAfterSig.md +++ b/docs/description/Sorbet_EmptyLineAfterSig.md @@ -1,12 +1,9 @@ Checks for blank lines after signatures. -It also suggests an autocorrect - # Examples ```ruby - # bad sig { void } diff --git a/docs/description/Sorbet_ForbidTStruct.md b/docs/description/Sorbet_ForbidTStruct.md new file mode 100644 index 00000000..fc0e99ff --- /dev/null +++ b/docs/description/Sorbet_ForbidTStruct.md @@ -0,0 +1,36 @@ + +Disallow using `T::Struct` and `T::Props`. + +# Examples + +```ruby + +# bad +class MyStruct < T::Struct + const :foo, String + prop :bar, Integer, default: 0 + + def some_method; end +end + +# good +class MyStruct + extend T::Sig + + sig { returns(String) } + attr_reader :foo + + sig { returns(Integer) } + attr_accessor :bar + + sig { params(foo: String, bar: Integer) } + def initialize(foo:, bar: 0) + @foo = foo + @bar = bar + end + + def some_method; end +end +``` + +[Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Sorbet/ForbidTStruct) \ No newline at end of file diff --git a/docs/description/Sorbet_SignatureBuildOrder.md b/docs/description/Sorbet_SignatureBuildOrder.md index a1bbd35b..7a4e79f8 100644 --- a/docs/description/Sorbet_SignatureBuildOrder.md +++ b/docs/description/Sorbet_SignatureBuildOrder.md @@ -1,4 +1,25 @@ +Checks for the correct order of sig builder methods: +- abstract, override, or overridable +- type_parameters +- params +- returns, or void +- soft, checked, or on_failure + # bad + sig { returns(Integer).params(x: Integer) } + + # good + sig { params(x: Integer).returns(Integer) } + +# Examples + +```ruby +# bad +sig { void.abstract } + +# good +sig { abstract.void } +``` [Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Sorbet/SignatureBuildOrder) \ No newline at end of file diff --git a/docs/description/Style_ArrayIntersect.md b/docs/description/Style_ArrayIntersect.md index ab688e48..c2405f10 100644 --- a/docs/description/Style_ArrayIntersect.md +++ b/docs/description/Style_ArrayIntersect.md @@ -7,6 +7,15 @@ can be replaced by `array1.intersect?(array2)`. The `array1.intersect?(array2)` method is faster than `(array1 & array2).any?` and is more readable. +In cases like the following, compatibility is not ensured, +so it will not be detected when using block argument. + +[source,ruby] +---- +([1] & [1,2]).any? { |x| false } # => false +[1].intersect?([1,2]) { |x| false } # => true +---- + # Examples ```ruby diff --git a/docs/description/Style_CollectionMethods.md b/docs/description/Style_CollectionMethods.md index 851aeb4e..89f54729 100644 --- a/docs/description/Style_CollectionMethods.md +++ b/docs/description/Style_CollectionMethods.md @@ -18,6 +18,7 @@ e.g. to use `detect` over `find`: # bad items.collect items.collect! +items.collect_concat items.inject items.detect items.find_all @@ -26,6 +27,7 @@ items.member? # good items.map items.map! +items.flat_map items.reduce items.find items.select diff --git a/docs/description/Style_FormatString.md b/docs/description/Style_FormatString.md index e6d8dea4..93ef6759 100644 --- a/docs/description/Style_FormatString.md +++ b/docs/description/Style_FormatString.md @@ -1,12 +1,24 @@ Enforces the use of a single string formatting utility. -Valid options include Kernel#format, Kernel#sprintf and String#%. +Valid options include `Kernel#format`, `Kernel#sprintf`, and `String#%`. -The detection of String#% cannot be implemented in a reliable +The detection of `String#%` cannot be implemented in a reliable manner for all cases, so only two scenarios are considered - if the first argument is a string literal and if the second argument is an array literal. +Autocorrection will be applied when using argument is a literal or known built-in conversion +methods such as `to_d`, `to_f`, `to_h`, `to_i`, `to_r`, `to_s`, and `to_sym` on variables, +provided that their return value is not an array. For example, when using `to_s`, +`'%s' % [1, 2, 3].to_s` can be autocorrected without any incompatibility: + +[source,ruby] +---- +'%s' % [1, 2, 3] #=> '1' +format('%s', [1, 2, 3]) #=> '[1, 2, 3]' +'%s' % [1, 2, 3].to_s #=> '[1, 2, 3]' +---- + # Examples ```ruby diff --git a/docs/description/Style_GuardClause.md b/docs/description/Style_GuardClause.md index 56b3aa45..d2bc3131 100644 --- a/docs/description/Style_GuardClause.md +++ b/docs/description/Style_GuardClause.md @@ -51,7 +51,26 @@ end # good foo || raise('exception') if something -ok# bad +ok + +# bad +define_method(:test) do + if something + work + end +end + +# good +define_method(:test) do + return unless something + + work +end + +# also good +define_method(:test) do + work if something +end# bad def test if foo? work diff --git a/docs/description/Style_RedundantDoubleSplatHashBraces.md b/docs/description/Style_RedundantDoubleSplatHashBraces.md index a6a1de09..bdcd7c63 100644 --- a/docs/description/Style_RedundantDoubleSplatHashBraces.md +++ b/docs/description/Style_RedundantDoubleSplatHashBraces.md @@ -10,6 +10,12 @@ do_something(**{foo: bar, baz: qux}) # good do_something(foo: bar, baz: qux) + +# bad +do_something(**{foo: bar, baz: qux}.merge(options)) + +# good +do_something(foo: bar, baz: qux, **options) ``` [Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/RedundantDoubleSplatHashBraces) \ No newline at end of file diff --git a/docs/description/Style_RedundantException.md b/docs/description/Style_RedundantException.md index b81e37a9..a1eefe54 100644 --- a/docs/description/Style_RedundantException.md +++ b/docs/description/Style_RedundantException.md @@ -1,19 +1,22 @@ Checks for RuntimeError as the argument of raise/fail. -It checks for code like this: - # Examples ```ruby -# Bad +# bad raise RuntimeError, 'message' - -# Bad raise RuntimeError.new('message') -# Good +# good raise 'message' + +# bad - message is not a string +raise RuntimeError, Object.new +raise RuntimeError.new(Object.new) + +# good +raise Object.new.to_s ``` [Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/RedundantException) \ No newline at end of file diff --git a/docs/description/Style_RedundantFilterChain.md b/docs/description/Style_RedundantFilterChain.md index 60ef41fe..11685e4c 100644 --- a/docs/description/Style_RedundantFilterChain.md +++ b/docs/description/Style_RedundantFilterChain.md @@ -21,11 +21,20 @@ arr.none? { |x| x > 1 } # good relation.select(:name).any? arr.select { |x| x > 1 }.any?(&:odd?)# good -arr.select { |x| x > 1 }.many?# bad +arr.select { |x| x > 1 }.many? + +# good +arr.select { |x| x > 1 }.present?# bad arr.select { |x| x > 1 }.many? # good arr.many? { |x| x > 1 } + +# bad +arr.select { |x| x > 1 }.present? + +# good +arr.any? { |x| x > 1 } ``` [Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/RedundantFilterChain) \ No newline at end of file diff --git a/docs/description/Style_ReturnNil.md b/docs/description/Style_ReturnNil.md index 14f5eb61..3346310d 100644 --- a/docs/description/Style_ReturnNil.md +++ b/docs/description/Style_ReturnNil.md @@ -1,7 +1,11 @@ -Enforces consistency between 'return nil' and 'return'. +Enforces consistency between `return nil` and `return`. -Supported styles are: return, return_nil. +This cop is disabled by default. Because there seems to be a perceived semantic difference +between `return` and `return nil`. The former can be seen as just halting evaluation, +while the latter might be used when the return value is of specific concern. + +Supported styles are `return` and `return_nil`. # Examples diff --git a/docs/description/Style_SingleLineDoEndBlock.md b/docs/description/Style_SingleLineDoEndBlock.md new file mode 100644 index 00000000..053b1d12 --- /dev/null +++ b/docs/description/Style_SingleLineDoEndBlock.md @@ -0,0 +1,27 @@ + +Checks for single-line `do`...`end` block. + +In practice a single line `do`...`end` is autocorrected when `EnforcedStyle: semantic` +in `Style/BlockDelimiters`. The autocorrection maintains the `do` ... `end` syntax to +preserve semantics and does not change it to `{`...`}` block. + +# Examples + +```ruby + +# bad +foo do |arg| bar(arg) end + +# good +foo do |arg| + bar(arg) +end + +# bad +->(arg) do bar(arg) end + +# good +->(arg) { bar(arg) } +``` + +[Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/SingleLineDoEndBlock) \ No newline at end of file diff --git a/docs/description/Style_YodaExpression.md b/docs/description/Style_YodaExpression.md index f6c40439..38191a5d 100644 --- a/docs/description/Style_YodaExpression.md +++ b/docs/description/Style_YodaExpression.md @@ -14,20 +14,21 @@ config.server_port = 9000 + ENV["TEST_ENV_NUMBER"].to_i ```ruby # bad -1 + x 10 * y +1 + x 1 & z +1 | x +1 ^ x 1 + CONST # good -60 * 24 -x + 1 y * 10 +x + 1 z & 1 +x | 1 +x ^ 1 CONST + 1 - -# good -1 | x +60 * 24 ``` [Source](http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/YodaExpression) \ No newline at end of file diff --git a/docs/description/description.json b/docs/description/description.json index 4f2e1413..60f8b277 100644 --- a/docs/description/description.json +++ b/docs/description/description.json @@ -2435,7 +2435,13 @@ "patternId": "Lint_RedundantRequireStatement", "title": "Checks for unnecessary `require` statement.", "description": "Checks for unnecessary `require` statement.", - "timeToFix": 5 + "timeToFix": 5, + "parameters": [ + { + "name": "SafeAutoCorrect", + "description": "SafeAutoCorrect" + } + ] }, { "patternId": "Lint_RedundantSafeNavigation", @@ -3751,6 +3757,10 @@ "description": "Enforces the use of `Object#instance_of?` instead of class comparison for equality.", "timeToFix": 5, "parameters": [ + { + "name": "SafeAutoCorrect", + "description": "SafeAutoCorrect" + }, { "name": "AllowedMethods", "description": "AllowedMethods" @@ -4987,7 +4997,13 @@ "patternId": "Style_RedundantFilterChain", "title": "Identifies usages of `any?`, `empty?`, `none?` or `one?` predicate methods chained to `select`/`filter`/`find_all` and change them to use predicate method instead.", "description": "Identifies usages of `any?`, `empty?`, `none?` or `one?` predicate methods chained to `select`/`filter`/`find_all` and change them to use predicate method instead.", - "timeToFix": 5 + "timeToFix": 5, + "parameters": [ + { + "name": "SafeAutoCorrect", + "description": "SafeAutoCorrect" + } + ] }, { "patternId": "Style_RedundantHeredocDelimiterQuotes", @@ -5059,6 +5075,12 @@ } ] }, + { + "patternId": "Style_SingleLineDoEndBlock", + "title": "Checks for single-line `do`...`end` blocks.", + "description": "Checks for single-line `do`...`end` blocks.", + "timeToFix": 5 + }, { "patternId": "Style_SoleNestedConditional", "title": "Finds sole nested conditional nodes which can be merged into outer conditional node.", @@ -7387,6 +7409,22 @@ } ] }, + { + "patternId": "Rails_DangerousColumnNames", + "title": "Avoid dangerous column names.", + "description": "Avoid dangerous column names.", + "timeToFix": 5, + "parameters": [ + { + "name": "Severity", + "description": "Severity" + }, + { + "name": "Include", + "description": "Include" + } + ] + }, { "patternId": "Rails_Date", "title": "Checks the correct usage of date aware methods, such as Date.today, Date.current etc.", @@ -7541,6 +7579,12 @@ } ] }, + { + "patternId": "Rails_EnvLocal", + "title": "Use `Rails.env.local?` instead of `Rails.env.development? || Rails.env.test?`.", + "description": "Use `Rails.env.local?` instead of `Rails.env.development? || Rails.env.test?`.", + "timeToFix": 5 + }, { "patternId": "Rails_EnvironmentComparison", "title": "Favor `Rails.env.production?` over `Rails.env == 'production'`.", @@ -7618,10 +7662,6 @@ { "name": "IgnoreWhereFirst", "description": "IgnoreWhereFirst" - }, - { - "name": "Include", - "description": "Include" } ] }, @@ -7641,10 +7681,6 @@ "name": "Safe", "description": "Safe" }, - { - "name": "Include", - "description": "Include" - }, { "name": "AllowedMethods", "description": "AllowedMethods" @@ -7737,6 +7773,14 @@ "description": "Checks for places where I18n \"lazy\" lookup can be used.", "timeToFix": 5, "parameters": [ + { + "name": "EnforcedStyle", + "description": "EnforcedStyle" + }, + { + "name": "SupportedStyles", + "description": "SupportedStyles" + }, { "name": "Include", "description": "Include" @@ -7899,6 +7943,14 @@ "description": "Do not add a NOT NULL column without a default value.", "timeToFix": 5, "parameters": [ + { + "name": "Database", + "description": "Database" + }, + { + "name": "SupportedDatabases", + "description": "SupportedDatabases" + }, { "name": "Include", "description": "Include" @@ -8053,6 +8105,22 @@ } ] }, + { + "patternId": "Rails_RedundantActiveRecordAllMethod", + "title": "Detect redundant `all` used as a receiver for Active Record query methods.", + "description": "Detect redundant `all` used as a receiver for Active Record query methods.", + "timeToFix": 5, + "parameters": [ + { + "name": "Safe", + "description": "Safe" + }, + { + "name": "AllowedReceivers", + "description": "AllowedReceivers" + } + ] + }, { "patternId": "Rails_RedundantAllowNil", "title": "Finds redundant use of `allow_nil` when `allow_blank` is set to certain values in model validations.", @@ -8311,6 +8379,18 @@ } ] }, + { + "patternId": "Rails_SelectMap", + "title": "Checks for uses of `select(:column_name)` with `map(&:column_name)`.", + "description": "Checks for uses of `select(:column_name)` with `map(&:column_name)`.", + "timeToFix": 5, + "parameters": [ + { + "name": "Safe", + "description": "Safe" + } + ] + }, { "patternId": "Rails_ShortI18n", "title": "Use the short form of the I18n methods: `t` instead of `translate` and `l` instead of `localize`.", @@ -8465,7 +8545,13 @@ "patternId": "Rails_TransactionExitStatement", "title": "Avoid the usage of `return`, `break` and `throw` in transaction blocks.", "description": "Avoid the usage of `return`, `break` and `throw` in transaction blocks.", - "timeToFix": 5 + "timeToFix": 5, + "parameters": [ + { + "name": "TransactionMethods", + "description": "TransactionMethods" + } + ] }, { "patternId": "Rails_UniqBeforePluck", @@ -8527,6 +8613,18 @@ } ] }, + { + "patternId": "Rails_UnusedRenderContent", + "title": "Do not specify body content for a response with a non-content status code.", + "description": "Do not specify body content for a response with a non-content status code.", + "timeToFix": 5, + "parameters": [ + { + "name": "Severity", + "description": "Severity" + } + ] + }, { "patternId": "Rails_Validation", "title": "Use validates :attribute, hash of validations.", @@ -8655,6 +8753,18 @@ } ] }, + { + "patternId": "Sorbet_ForbidTStruct", + "title": "Forbid usage of T::Struct.", + "description": "Forbid usage of T::Struct.", + "timeToFix": 5, + "parameters": [ + { + "name": "Safe", + "description": "Safe" + } + ] + }, { "patternId": "Sorbet_ForbidTUnsafe", "title": "Forbid usage of T.unsafe.", @@ -8711,6 +8821,22 @@ } ] }, + { + "patternId": "Sorbet_BuggyObsoleteStrictMemoization", + "title": "Checks for the a mistaken variant of the \"obsolete memoization pattern\" that used to be required for older Sorbet versions in `#typed: strict` files.", + "description": "Checks for the a mistaken variant of the \"obsolete memoization pattern\" that used to be required for older Sorbet versions in `#typed: strict` files. The mistaken variant would overwrite the ivar with `nil` on every call, causing the memoized value to be discarded and recomputed on every call.\nThis cop will correct it to read from the ivar instead of `nil`, which will memoize it correctly.\nThe result of this correction will be the \"obsolete memoization pattern\", which can further be corrected by the `Sorbet/ObsoleteStrictMemoization` cop.\nSee `Sorbet/ObsoleteStrictMemoization` for more details.", + "timeToFix": 5, + "parameters": [ + { + "name": "Safe", + "description": "Safe" + }, + { + "name": "SafeAutoCorrect", + "description": "SafeAutoCorrect" + } + ] + }, { "patternId": "Sorbet_ForbidExtendTSigHelpersInShims", "title": "Forbid the use of `extend T::Sig` and `extend T::Helpers` in RBI shims", diff --git a/docs/patterns.json b/docs/patterns.json index 09757fbc..26b3505f 100644 --- a/docs/patterns.json +++ b/docs/patterns.json @@ -1,6 +1,6 @@ { "name": "rubocop", - "version": "1.56.1", + "version": "1.57.2", "patterns": [ { "patternId": "Migration_DepartmentName", @@ -2757,6 +2757,12 @@ "patternId": "Lint_RedundantRequireStatement", "level": "Warning", "category": "ErrorProne", + "parameters": [ + { + "name": "SafeAutoCorrect", + "default": "false" + } + ], "enabled": false }, { @@ -2897,6 +2903,7 @@ "present?", "blank?", "presence", + "presence_in", "try", "try!", "in?" @@ -4312,6 +4319,10 @@ "level": "Info", "category": "CodeStyle", "parameters": [ + { + "name": "SafeAutoCorrect", + "default": "false" + }, { "name": "AllowedMethods", "default": [ @@ -4389,7 +4400,7 @@ }, { "name": "PreferredMethods", - "default": "{\"collect\"=>\"map\", \"collect!\"=>\"map!\", \"inject\"=>\"reduce\", \"detect\"=>\"find\", \"find_all\"=>\"select\", \"member?\"=>\"include?\"}" + "default": "{\"collect\"=>\"map\", \"collect!\"=>\"map!\", \"collect_concat\"=>\"flat_map\", \"inject\"=>\"reduce\", \"detect\"=>\"find\", \"find_all\"=>\"select\", \"member?\"=>\"include?\"}" }, { "name": "MethodsAcceptingSymbol", @@ -5343,7 +5354,7 @@ }, { "name": "InverseMethods", - "default": "{:!==>:==, :>=>:<=, :<==>:>, :<=>:>=, :>==>:<, :!~=>:=~, :zero?=>:nonzero?, :nonzero?=>:zero?, :any?=>:none?, :none?=>:any?, :even?=>:odd?, :odd?=>:even?}" + "default": "{:!==>:==, :>=>:<=, :<==>:>, :<=>:>=, :>==>:<, :!~=>:=~, :zero?=>:nonzero?, :nonzero?=>:zero?, :any?=>:none?, :none?=>:any?, :even?=>:odd?, :odd?=>:even?, :present?=>:blank?, :blank?=>:present?, :include?=>:exclude?, :exclude?=>:include?}" } ], "enabled": false @@ -5686,6 +5697,12 @@ "patternId": "Style_RedundantFilterChain", "level": "Info", "category": "CodeStyle", + "parameters": [ + { + "name": "SafeAutoCorrect", + "default": "false" + } + ], "enabled": false }, { @@ -5758,6 +5775,12 @@ ], "enabled": false }, + { + "patternId": "Style_SingleLineDoEndBlock", + "level": "Info", + "category": "CodeStyle", + "enabled": false + }, { "patternId": "Style_SoleNestedConditional", "level": "Info", @@ -8339,6 +8362,24 @@ ], "enabled": false }, + { + "patternId": "Rails_DangerousColumnNames", + "level": "Warning", + "category": "ErrorProne", + "parameters": [ + { + "name": "Severity", + "default": "warning" + }, + { + "name": "Include", + "default": [ + "db/**/*.rb" + ] + } + ], + "enabled": false + }, { "patternId": "Rails_Date", "level": "Warning", @@ -8509,6 +8550,12 @@ ], "enabled": false }, + { + "patternId": "Rails_EnvLocal", + "level": "Warning", + "category": "ErrorProne", + "enabled": false + }, { "patternId": "Rails_EnvironmentComparison", "level": "Warning", @@ -8599,12 +8646,6 @@ { "name": "IgnoreWhereFirst", "default": "true" - }, - { - "name": "Include", - "default": [ - "app/models/**/*.rb" - ] } ], "enabled": false @@ -8624,12 +8665,6 @@ "name": "Safe", "default": "false" }, - { - "name": "Include", - "default": [ - "app/models/**/*.rb" - ] - }, { "name": "AllowedMethods", "default": [ @@ -8741,6 +8776,17 @@ "level": "Warning", "category": "ErrorProne", "parameters": [ + { + "name": "EnforcedStyle", + "default": "lazy" + }, + { + "name": "SupportedStyles", + "default": [ + "lazy", + "explicit" + ] + }, { "name": "Include", "default": [ @@ -8923,6 +8969,16 @@ "level": "Warning", "category": "ErrorProne", "parameters": [ + { + "name": "Database", + "default": "" + }, + { + "name": "SupportedDatabases", + "default": [ + "mysql" + ] + }, { "name": "Include", "default": [ @@ -9095,6 +9151,25 @@ ], "enabled": false }, + { + "patternId": "Rails_RedundantActiveRecordAllMethod", + "level": "Warning", + "category": "ErrorProne", + "parameters": [ + { + "name": "Safe", + "default": "false" + }, + { + "name": "AllowedReceivers", + "default": [ + "ActionMailer::Preview", + "ActiveSupport::TimeZone" + ] + } + ], + "enabled": false + }, { "patternId": "Rails_RedundantAllowNil", "level": "Warning", @@ -9379,6 +9454,18 @@ ], "enabled": false }, + { + "patternId": "Rails_SelectMap", + "level": "Warning", + "category": "ErrorProne", + "parameters": [ + { + "name": "Safe", + "default": "false" + } + ], + "enabled": false + }, { "patternId": "Rails_ShortI18n", "level": "Warning", @@ -9572,6 +9659,14 @@ "patternId": "Rails_TransactionExitStatement", "level": "Warning", "category": "ErrorProne", + "parameters": [ + { + "name": "TransactionMethods", + "default": [ + + ] + } + ], "enabled": false }, { @@ -9645,6 +9740,18 @@ ], "enabled": false }, + { + "patternId": "Rails_UnusedRenderContent", + "level": "Warning", + "category": "ErrorProne", + "parameters": [ + { + "name": "Severity", + "default": "warning" + } + ], + "enabled": false + }, { "patternId": "Rails_Validation", "level": "Warning", @@ -9780,6 +9887,18 @@ ], "enabled": false }, + { + "patternId": "Sorbet_ForbidTStruct", + "level": "Info", + "category": "CodeStyle", + "parameters": [ + { + "name": "Safe", + "default": "false" + } + ], + "enabled": false + }, { "patternId": "Sorbet_ForbidTUnsafe", "level": "Info", @@ -9842,6 +9961,22 @@ ], "enabled": false }, + { + "patternId": "Sorbet_BuggyObsoleteStrictMemoization", + "level": "Info", + "category": "CodeStyle", + "parameters": [ + { + "name": "Safe", + "default": "true" + }, + { + "name": "SafeAutoCorrect", + "default": "false" + } + ], + "enabled": false + }, { "patternId": "Sorbet_ForbidExtendTSigHelpersInShims", "level": "Info",