From ccdb63d36edac93ed08c7101e0e696a9e96c0829 Mon Sep 17 00:00:00 2001 From: Brian Hawley Date: Fri, 8 Nov 2024 18:33:12 -0600 Subject: [PATCH] Update rubocop to 1.68.0 - General bundle update. - Update the docs too. - Fix rubocop API deprecations. - Fix reasonable rubocop complaints. - Disable unnecessary rubocop complaints. - Explicit ostruct dependency for future compatibility. - Remove an unnecessary empty file. --- .rubocop.yml | 30 ++++++- .rubocop_todo.yml | 13 ++++ Gemfile | 3 +- Gemfile.lock | 78 ++++++++++--------- bin/codeclimate-rubocop | 2 +- .../gemspec/add_runtime_dependency.md | 14 ++++ .../contents/gemspec/duplicated_assignment.md | 4 +- .../gemspec/ruby_version_globals_usage.md | 6 +- .../contents/layout/assignment_indentation.md | 6 +- config/contents/layout/block_alignment.md | 2 +- config/contents/layout/condition_position.md | 4 - .../layout/first_argument_indentation.md | 4 +- .../layout/first_array_element_indentation.md | 3 - .../first_method_argument_line_break.md | 6 ++ config/contents/layout/heredoc_indentation.md | 2 +- config/contents/layout/indentation_width.md | 9 +-- .../contents/layout/leading_comment_space.md | 37 +++++++++ config/contents/layout/line_length.md | 40 +++++----- .../lint/ambiguous_block_association.md | 2 - config/contents/lint/ambiguous_operator.md | 2 - .../contents/lint/ambiguous_regexp_literal.md | 2 - config/contents/lint/boolean_symbol.md | 2 - .../lint/circular_argument_reference.md | 13 ---- config/contents/lint/debugger.md | 4 - .../lint/deprecated_open_ssl_constant.md | 10 --- config/contents/lint/duplicate_branch.md | 13 ++++ .../contents/lint/duplicate_case_condition.md | 4 - config/contents/lint/duplicate_hash_key.md | 4 - config/contents/lint/duplicate_methods.md | 10 --- config/contents/lint/duplicate_set_element.md | 21 +++++ .../lint/each_with_object_argument.md | 4 - config/contents/lint/else_layout.md | 2 - config/contents/lint/empty_ensure.md | 12 +-- config/contents/lint/empty_interpolation.md | 4 - config/contents/lint/empty_when.md | 2 - config/contents/lint/ensure_return.md | 7 +- config/contents/lint/float_comparison.md | 2 +- config/contents/lint/float_out_of_range.md | 4 - .../lint/format_parameter_mismatch.md | 10 --- .../lint/implicit_string_concatenation.md | 4 - .../lint/ineffective_access_modifier.md | 7 -- config/contents/lint/interpolation_check.md | 4 - .../contents/lint/literal_in_interpolation.md | 4 - config/contents/lint/loop.md | 18 ++--- .../contents/lint/nested_method_definition.md | 6 -- .../contents/lint/next_without_accumulator.md | 4 - .../lint/no_return_in_begin_end_blocks.md | 5 -- config/contents/lint/percent_string_array.md | 4 - config/contents/lint/percent_symbol_array.md | 4 - config/contents/lint/rand_one.md | 4 - .../lint/redundant_cop_enable_directive.md | 4 +- .../lint/redundant_splat_expansion.md | 2 +- .../lint/redundant_string_coercion.md | 4 - config/contents/lint/require_parentheses.md | 4 - config/contents/lint/rescue_exception.md | 4 - .../contents/lint/return_in_void_context.md | 2 - config/contents/lint/safe_navigation_chain.md | 4 - .../lint/safe_navigation_consistency.md | 26 +++++-- .../lint/shadowing_outer_local_variable.md | 14 ++-- .../lint/unescaped_bracket_in_regexp.md | 22 ++++++ config/contents/lint/unified_integer.md | 4 - config/contents/lint/unreachable_code.md | 5 -- config/contents/lint/uri_regexp.md | 18 ++++- config/contents/lint/useless_assignment.md | 16 ++-- .../lint/useless_else_without_rescue.md | 4 - .../lint/useless_numeric_operation.md | 25 ++++++ config/contents/lint/useless_setter_call.md | 4 - config/contents/metrics/block_length.md | 11 +-- config/contents/metrics/block_nesting.md | 10 +-- config/contents/metrics/class_length.md | 11 +-- .../contents/metrics/cyclomatic_complexity.md | 5 +- config/contents/metrics/method_length.md | 11 +-- config/contents/metrics/module_length.md | 11 +-- config/contents/naming/predicate_name.md | 68 +++++++++------- .../style/access_modifier_declarations.md | 4 + config/contents/style/accessor_grouping.md | 3 + .../ambiguous_endless_method_definition.md | 23 ++++++ config/contents/style/bitwise_predicate.md | 26 +++++++ config/contents/style/collection_compact.md | 4 +- config/contents/style/combinable_defined.md | 18 +++++ config/contents/style/combinable_loops.md | 3 + config/contents/style/commented_keyword.md | 2 +- config/contents/style/def_with_parentheses.md | 2 - config/contents/style/each_for_simple_loop.md | 1 - config/contents/style/empty_literal.md | 2 + config/contents/style/eval_with_location.md | 22 +++--- config/contents/style/file_read.md | 7 +- config/contents/style/file_write.md | 7 +- config/contents/style/format_string_token.md | 4 +- config/contents/style/hash_except.md | 6 +- config/contents/style/hash_syntax.md | 4 +- .../style/if_with_boolean_literal_branches.md | 1 - .../style/keyword_arguments_merging.md | 14 ++++ .../map_compact_with_conditional_block.md | 4 + config/contents/style/map_into_array.md | 14 +++- .../method_call_with_args_parentheses.md | 2 +- .../method_call_without_args_parentheses.md | 4 +- config/contents/style/numeric_predicate.md | 4 +- config/contents/style/quoted_symbols.md | 2 +- config/contents/style/redundant_condition.md | 1 - .../redundant_file_extension_in_require.md | 2 +- .../style/redundant_interpolation_unfreeze.md | 14 ++++ ...turn_nil_in_predicate_method_definition.md | 21 ++++- config/contents/style/safe_navigation.md | 9 ++- .../style/safe_navigation_chain_length.md | 19 +++++ config/contents/style/select_by_regexp.md | 2 +- .../style/send_with_literal_method_name.md | 13 ++++ config/contents/style/super_arguments.md | 20 ++++- config/contents/style/while_until_do.md | 2 - config/contents/style/while_until_modifier.md | 1 - lib/cc/engine/file_list_resolver.rb | 10 +-- lib/cc/engine/fingerprint.rb | 2 +- lib/cc/engine/issue.rb | 5 +- lib/cc/engine/source_file.rb | 6 +- spec/cc/engine/category_parser_spec.rb | 2 + spec/cc/engine/content_resolver_spec.rb | 6 +- spec/cc/engine/file_list_resolver_spec.rb | 7 +- spec/cc/engine/fingerprint_spec.rb | 4 +- spec/cc/engine/issue_spec.rb | 2 + spec/cc/engine/rubocop_spec.rb | 10 ++- spec/cc/engine/source_file_spec.rb | 0 spec/rubocop/config_patch_spec.rb | 3 +- spec/rubocop/cop_patches_spec.rb | 4 +- spec/spec_helper.rb | 2 + spec/support/filesystem_helpers.rb | 2 + spec/support/matchers.rb | 2 + spec/support/rubocop_runner.rb | 4 +- 127 files changed, 670 insertions(+), 438 deletions(-) create mode 100644 .rubocop_todo.yml create mode 100644 config/contents/gemspec/add_runtime_dependency.md create mode 100644 config/contents/lint/duplicate_set_element.md create mode 100644 config/contents/lint/unescaped_bracket_in_regexp.md create mode 100644 config/contents/lint/useless_numeric_operation.md create mode 100644 config/contents/style/ambiguous_endless_method_definition.md create mode 100644 config/contents/style/bitwise_predicate.md create mode 100644 config/contents/style/combinable_defined.md create mode 100644 config/contents/style/keyword_arguments_merging.md create mode 100644 config/contents/style/redundant_interpolation_unfreeze.md create mode 100644 config/contents/style/safe_navigation_chain_length.md delete mode 100644 spec/cc/engine/source_file_spec.rb diff --git a/.rubocop.yml b/.rubocop.yml index 510e51f2..e0b78f80 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,10 +1,15 @@ -inherit_from: base_rubocop.yml - require: rubocop-rspec +inherit_from: + - .rubocop_todo.yml + - base_rubocop.yml + Layout/MultilineOperationIndentation: Enabled: false +Naming/HeredocDelimiterNaming: + Enabled: false + Naming/FileName: Exclude: - 'bin/codeclimate-rubocop' @@ -20,3 +25,24 @@ Style/TrailingCommaInHashLiteral: Style/TrailingCommaInArguments: Enabled: false + +RSpec/AnyInstance: + Enabled: false + +RSpec/ContextWording: + Enabled: false + +RSpec/DescribedClass: + Enabled: false + +RSpec/ExampleLength: + Enabled: false + +RSpec/MessageChain: + Enabled: false + +RSpec/MultipleExpectations: + Enabled: false + +RSpec/NotToNot: + Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000..dcc17406 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,13 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2024-11-08 23:41:07 UTC using RuboCop version 1.68.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 1 +# Configuration parameters: AllowComments, AllowNil. +Lint/SuppressedException: + Exclude: + - 'Rakefile' diff --git a/Gemfile b/Gemfile index 6683f2fc..7f5f6ef4 100644 --- a/Gemfile +++ b/Gemfile @@ -5,7 +5,7 @@ source 'https://rubygems.org' gem "activesupport", require: false gem "parser" gem "pry", require: false -gem "rubocop", "1.64.1", require: false +gem "rubocop", "1.68.0", require: false gem "rubocop-capybara", require: false gem "rubocop-factory_bot", require: false gem "rubocop-graphql", require: false @@ -24,6 +24,7 @@ gem "rubocop-thread_safety", require: false gem "test-prof", require: false group :test do + gem "ostruct", require: false gem "rake" gem "rspec" end diff --git a/Gemfile.lock b/Gemfile.lock index 6ce40714..d4f90fcd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,89 +1,91 @@ GEM remote: https://rubygems.org/ specs: - activesupport (7.1.3.4) + activesupport (8.0.0) base64 + benchmark (>= 0.3) bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) ast (2.4.2) base64 (0.2.0) + benchmark (0.4.0) bigdecimal (3.1.8) coderay (1.1.3) - concurrent-ruby (1.3.3) + concurrent-ruby (1.3.4) connection_pool (2.4.1) diff-lcs (1.5.1) drb (2.2.1) - i18n (1.14.5) + i18n (1.14.6) concurrent-ruby (~> 1.0) - json (2.7.2) + json (2.8.1) language_server-protocol (3.17.0.3) + logger (1.6.1) method_source (1.1.0) - minitest (5.24.1) - mutex_m (0.2.0) - parallel (1.25.1) - parser (3.3.3.0) + minitest (5.25.1) + ostruct (0.6.1) + parallel (1.26.3) + parser (3.3.6.0) ast (~> 2.4.1) racc pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) - racc (1.8.0) - rack (3.1.4) + racc (1.8.1) + rack (3.1.8) rainbow (3.1.1) rake (13.2.1) regexp_parser (2.9.2) - rexml (3.3.1) - strscan rspec (3.13.0) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) - rspec-core (3.13.0) + rspec-core (3.13.2) rspec-support (~> 3.13.0) - rspec-expectations (3.13.1) + rspec-expectations (3.13.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-mocks (3.13.1) + rspec-mocks (3.13.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-support (3.13.1) - rubocop (1.64.1) + rubocop (1.68.0) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.31.1, < 2.0) + regexp_parser (>= 2.4, < 3.0) + rubocop-ast (>= 1.32.2, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.31.3) + rubocop-ast (1.34.1) parser (>= 3.3.1.0) rubocop-capybara (2.21.0) rubocop (~> 1.41) rubocop-factory_bot (2.26.1) rubocop (~> 1.61) - rubocop-graphql (1.5.2) - rubocop (>= 0.90, < 2) + rubocop-graphql (1.5.4) + rubocop (>= 1.50, < 2) rubocop-i18n (3.0.0) rubocop (~> 1.0) - rubocop-minitest (0.35.0) + rubocop-minitest (0.36.0) rubocop (>= 1.61, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-performance (1.21.1) + rubocop-performance (1.22.1) rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails (2.25.1) + rubocop-rails (2.27.0) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 1.33.0, < 2.0) + rubocop (>= 1.52.0, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) rubocop-rails-omakase (1.0.0) rubocop @@ -92,36 +94,38 @@ GEM rubocop-rails rubocop-rake (0.6.0) rubocop (~> 1.0) - rubocop-rspec (3.0.1) + rubocop-rspec (3.2.0) rubocop (~> 1.61) rubocop-rspec_rails (2.30.0) rubocop (~> 1.61) rubocop-rspec (~> 3, >= 3.0.1) - rubocop-sequel (0.3.4) + rubocop-sequel (0.3.7) rubocop (~> 1.0) rubocop-shopify (2.15.1) rubocop (~> 1.51) - rubocop-sorbet (0.8.3) - rubocop (>= 0.90.0) + rubocop-sorbet (0.8.7) + rubocop (>= 1) rubocop-thread_safety (0.5.1) rubocop (>= 0.90.0) ruby-progressbar (1.13.0) - strscan (3.1.0) - test-prof (1.3.3.1) + securerandom (0.3.1) + test-prof (1.4.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (2.5.0) + unicode-display_width (2.6.0) + uri (1.0.1) PLATFORMS ruby DEPENDENCIES activesupport + ostruct parser pry rake rspec - rubocop (= 1.64.1) + rubocop (= 1.68.0) rubocop-capybara rubocop-factory_bot rubocop-graphql diff --git a/bin/codeclimate-rubocop b/bin/codeclimate-rubocop index 7bca1975..6f36157f 100755 --- a/bin/codeclimate-rubocop +++ b/bin/codeclimate-rubocop @@ -14,4 +14,4 @@ engine_config = {} end -CC::Engine::Rubocop.new(Dir.pwd, engine_config, STDOUT).run +CC::Engine::Rubocop.new(Dir.pwd, engine_config, $stdout).run diff --git a/config/contents/gemspec/add_runtime_dependency.md b/config/contents/gemspec/add_runtime_dependency.md new file mode 100644 index 00000000..8605709d --- /dev/null +++ b/config/contents/gemspec/add_runtime_dependency.md @@ -0,0 +1,14 @@ +Prefer `add_dependency` over `add_runtime_dependency` as the latter is +considered soft-deprecated. + +### Example: + + # bad + Gem::Specification.new do |spec| + spec.add_runtime_dependency('rubocop') + end + + # good + Gem::Specification.new do |spec| + spec.add_dependency('rubocop') + end diff --git a/config/contents/gemspec/duplicated_assignment.md b/config/contents/gemspec/duplicated_assignment.md index 6afaac86..a51a6e95 100644 --- a/config/contents/gemspec/duplicated_assignment.md +++ b/config/contents/gemspec/duplicated_assignment.md @@ -26,6 +26,6 @@ permitted because it is the intended use of appending values. # good Gem::Specification.new do |spec| - spec.add_runtime_dependency('parallel', '~> 1.10') - spec.add_runtime_dependency('parser', '>= 2.3.3.1', '< 3.0') + spec.add_dependency('parallel', '~> 1.10') + spec.add_dependency('parser', '>= 2.3.3.1', '< 3.0') end \ No newline at end of file diff --git a/config/contents/gemspec/ruby_version_globals_usage.md b/config/contents/gemspec/ruby_version_globals_usage.md index 953f14f8..19aed44d 100644 --- a/config/contents/gemspec/ruby_version_globals_usage.md +++ b/config/contents/gemspec/ruby_version_globals_usage.md @@ -9,13 +9,13 @@ to execute `rake release` and not user's ruby version. # bad Gem::Specification.new do |spec| if RUBY_VERSION >= '3.0' - spec.add_runtime_dependency 'gem_a' + spec.add_dependency 'gem_a' else - spec.add_runtime_dependency 'gem_b' + spec.add_dependency 'gem_b' end end # good Gem::Specification.new do |spec| - spec.add_runtime_dependency 'gem_a' + spec.add_dependency 'gem_a' end diff --git a/config/contents/layout/assignment_indentation.md b/config/contents/layout/assignment_indentation.md index dfe6f902..eb9166a9 100644 --- a/config/contents/layout/assignment_indentation.md +++ b/config/contents/layout/assignment_indentation.md @@ -1,6 +1,9 @@ Checks the indentation of the first line of the right-hand-side of a multi-line assignment. +The indentation of the remaining lines can be corrected with +other cops such as `Layout/IndentationConsistency` and `Layout/EndAlignment`. + ### Example: # bad value = @@ -13,6 +16,3 @@ right-hand-side of a multi-line assignment. if foo 'bar' end - -The indentation of the remaining lines can be corrected with -other cops such as `IndentationConsistency` and `EndAlignment`. \ No newline at end of file diff --git a/config/contents/layout/block_alignment.md b/config/contents/layout/block_alignment.md index bc7e04f8..870c2fe6 100644 --- a/config/contents/layout/block_alignment.md +++ b/config/contents/layout/block_alignment.md @@ -11,7 +11,7 @@ start of the line where the `do` appeared. start of the line where the expression started. `either` (which is the default) : the `end` is allowed to be in either -location. The autofixer will default to `start_of_line`. +location. The autocorrect will default to `start_of_line`. ### Example: EnforcedStyleAlignWith: either (default) # bad diff --git a/config/contents/layout/condition_position.md b/config/contents/layout/condition_position.md index fd49e4b7..c9270184 100644 --- a/config/contents/layout/condition_position.md +++ b/config/contents/layout/condition_position.md @@ -4,16 +4,12 @@ if/while/until. ### Example: # bad - if some_condition do_something end -### Example: - # good - if some_condition do_something end \ No newline at end of file diff --git a/config/contents/layout/first_argument_indentation.md b/config/contents/layout/first_argument_indentation.md index 4164f922..3c0822a4 100644 --- a/config/contents/layout/first_argument_indentation.md +++ b/config/contents/layout/first_argument_indentation.md @@ -113,8 +113,8 @@ This cop will respect `Layout/ArgumentAlignment` and will not work when ### Example: EnforcedStyle: special_for_inner_method_call # The first argument should normally be indented one step more than - # the preceding line, but if it's a argument for a method call that - # is itself a argument in a method call, then the inner argument + # the preceding line, but if it's an argument for a method call that + # is itself an argument in a method call, then the inner argument # should be indented relative to the inner method. # good diff --git a/config/contents/layout/first_array_element_indentation.md b/config/contents/layout/first_array_element_indentation.md index 0e031b98..bb7bf464 100644 --- a/config/contents/layout/first_array_element_indentation.md +++ b/config/contents/layout/first_array_element_indentation.md @@ -46,7 +46,6 @@ styles are 'consistent' and 'align_brackets'. Here are examples: # defined inside a method call. # bad - # consistent array = [ :value ] @@ -67,13 +66,11 @@ styles are 'consistent' and 'align_brackets'. Here are examples: # brackets are indented to the same position. # bad - # align_brackets and_now_for_something = [ :completely_different ] # good - # align_brackets and_now_for_something = [ :completely_different ] \ No newline at end of file diff --git a/config/contents/layout/first_method_argument_line_break.md b/config/contents/layout/first_method_argument_line_break.md index 62a1936b..d30c0e3b 100644 --- a/config/contents/layout/first_method_argument_line_break.md +++ b/config/contents/layout/first_method_argument_line_break.md @@ -57,3 +57,9 @@ multi-line method call. qux: "b", } ) + +### Example: AllowedMethods: ['some_method'] + + # good + some_method(foo, bar, + baz) \ No newline at end of file diff --git a/config/contents/layout/heredoc_indentation.md b/config/contents/layout/heredoc_indentation.md index fdb29f2e..e63f5ee2 100644 --- a/config/contents/layout/heredoc_indentation.md +++ b/config/contents/layout/heredoc_indentation.md @@ -1,7 +1,7 @@ Checks the indentation of the here document bodies. The bodies are indented one step. -Note: When ``Layout/LineLength``'s `AllowHeredoc` is false (not default), +NOTE: When ``Layout/LineLength``'s `AllowHeredoc` is false (not default), this cop does not add any offenses for long here documents to avoid ``Layout/LineLength``'s offenses. diff --git a/config/contents/layout/indentation_width.md b/config/contents/layout/indentation_width.md index 1787a56b..b91ca7c4 100644 --- a/config/contents/layout/indentation_width.md +++ b/config/contents/layout/indentation_width.md @@ -1,10 +1,9 @@ -Checks for indentation that doesn't use the specified number -of spaces. +Checks for indentation that doesn't use the specified number of spaces. +The indentation width can be configured using the `Width` setting. The default width is 2. -See also the IndentationConsistency cop which is the companion to this -one. +See also the `Layout/IndentationConsistency` cop which is the companion to this one. -### Example: +### Example: Width: 2 (default) # bad class A def test diff --git a/config/contents/layout/leading_comment_space.md b/config/contents/layout/leading_comment_space.md index f9d9122a..22d2fb9d 100644 --- a/config/contents/layout/leading_comment_space.md +++ b/config/contents/layout/leading_comment_space.md @@ -43,3 +43,40 @@ or rackup options. #ruby=2.7.0 #ruby-gemset=myproject + +### Example: AllowRBSInlineAnnotation: false (default) + + # bad + + include Enumerable #[Integer] + + attr_reader :name #: String + attr_reader :age #: Integer? + +### Example: AllowRBSInlineAnnotation: true + + # good + + include Enumerable #[Integer] + + attr_reader :name #: String + attr_reader :age #: Integer? + +### Example: AllowSteepAnnotation: false (default) + + # bad + [1, 2, 3].each_with_object([]) do |n, list| #$ Array[Integer] + list << n + end + + name = 'John' #: String + +### Example: AllowSteepAnnotation: true + + # good + + [1, 2, 3].each_with_object([]) do |n, list| #$ Array[Integer] + list << n + end + + name = 'John' #: String diff --git a/config/contents/layout/line_length.md b/config/contents/layout/line_length.md index e98004ee..06b0e716 100644 --- a/config/contents/layout/line_length.md +++ b/config/contents/layout/line_length.md @@ -10,29 +10,29 @@ inserting line breaks into expressions that can be safely split across lines. These include arrays, hashes, and method calls with argument lists. -If autocorrection is enabled, the following Layout cops +If autocorrection is enabled, the following cops are recommended to further format the broken lines. (Many of these are enabled by default.) -* ArgumentAlignment -* ArrayAlignment -* BlockAlignment -* BlockDelimiters -* BlockEndNewline -* ClosingParenthesisIndentation -* FirstArgumentIndentation -* FirstArrayElementIndentation -* FirstHashElementIndentation -* FirstParameterIndentation -* HashAlignment -* IndentationWidth -* MultilineArrayLineBreaks -* MultilineBlockLayout -* MultilineHashBraceLayout -* MultilineHashKeyLineBreaks -* MultilineMethodArgumentLineBreaks -* MultilineMethodParameterLineBreaks -* ParameterAlignment +* `Layout/ArgumentAlignment` +* `Layout/ArrayAlignment` +* `Layout/BlockAlignment` +* `Layout/BlockEndNewline` +* `Layout/ClosingParenthesisIndentation` +* `Layout/FirstArgumentIndentation` +* `Layout/FirstArrayElementIndentation` +* `Layout/FirstHashElementIndentation` +* `Layout/FirstParameterIndentation` +* `Layout/HashAlignment` +* `Layout/IndentationWidth` +* `Layout/MultilineArrayLineBreaks` +* `Layout/MultilineBlockLayout` +* `Layout/MultilineHashBraceLayout` +* `Layout/MultilineHashKeyLineBreaks` +* `Layout/MultilineMethodArgumentLineBreaks` +* `Layout/MultilineMethodParameterLineBreaks` +* `Layout//ParameterAlignment` +* `Style/BlockDelimiters` Together, these cops will pretty print hashes, arrays, method calls, etc. For example, let's say the max columns diff --git a/config/contents/lint/ambiguous_block_association.md b/config/contents/lint/ambiguous_block_association.md index f7baee73..da639c17 100644 --- a/config/contents/lint/ambiguous_block_association.md +++ b/config/contents/lint/ambiguous_block_association.md @@ -9,8 +9,6 @@ By default, there are no methods to allowed. # bad some_method a { |val| puts val } -### Example: - # good # With parentheses, there's no ambiguity. some_method(a { |val| puts val }) diff --git a/config/contents/lint/ambiguous_operator.md b/config/contents/lint/ambiguous_operator.md index 99b3b9e5..5584c1d7 100644 --- a/config/contents/lint/ambiguous_operator.md +++ b/config/contents/lint/ambiguous_operator.md @@ -9,8 +9,6 @@ method invocation without parentheses. # a `*` method invocation (i.e. `do_something.*(some_array)`). do_something *some_array -### Example: - # good # With parentheses, there's no ambiguity. diff --git a/config/contents/lint/ambiguous_regexp_literal.md b/config/contents/lint/ambiguous_regexp_literal.md index 7ad32663..0a2fa316 100644 --- a/config/contents/lint/ambiguous_regexp_literal.md +++ b/config/contents/lint/ambiguous_regexp_literal.md @@ -10,8 +10,6 @@ a method invocation without parentheses. # (i.e. `do_something./(pattern)./(i)`) do_something /pattern/i -### Example: - # good # With parentheses, there's no ambiguity. diff --git a/config/contents/lint/boolean_symbol.md b/config/contents/lint/boolean_symbol.md index f677838e..b5d8304f 100644 --- a/config/contents/lint/boolean_symbol.md +++ b/config/contents/lint/boolean_symbol.md @@ -15,8 +15,6 @@ changed to actual booleans. # good true -### Example: - # bad :false diff --git a/config/contents/lint/circular_argument_reference.md b/config/contents/lint/circular_argument_reference.md index f8a70312..1cf52cee 100644 --- a/config/contents/lint/circular_argument_reference.md +++ b/config/contents/lint/circular_argument_reference.md @@ -6,39 +6,26 @@ This cop mirrors a warning produced by MRI since 2.2. ### Example: # bad - def bake(pie: pie) pie.heat_up end -### Example: - # good - def bake(pie:) pie.refrigerate end -### Example: - # good - def bake(pie: self.pie) pie.feed_to(user) end -### Example: - # bad - def cook(dry_ingredients = dry_ingredients) dry_ingredients.reduce(&:+) end -### Example: - # good - def cook(dry_ingredients = self.dry_ingredients) dry_ingredients.combine end \ No newline at end of file diff --git a/config/contents/lint/debugger.md b/config/contents/lint/debugger.md index a36224e0..a79583d5 100644 --- a/config/contents/lint/debugger.md +++ b/config/contents/lint/debugger.md @@ -37,8 +37,6 @@ be configured through `DebuggerRequires`. It has the same structure as do_something end -### Example: - # bad (ok during development) # using byebug @@ -47,8 +45,6 @@ be configured through `DebuggerRequires`. It has the same structure as do_something end -### Example: - # good def some_method diff --git a/config/contents/lint/deprecated_open_ssl_constant.md b/config/contents/lint/deprecated_open_ssl_constant.md index 96571a48..e6f7d7af 100644 --- a/config/contents/lint/deprecated_open_ssl_constant.md +++ b/config/contents/lint/deprecated_open_ssl_constant.md @@ -4,28 +4,18 @@ instead. ### Example: - # Example for OpenSSL::Cipher instantiation. - # bad OpenSSL::Cipher::AES.new(128, :GCM) # good OpenSSL::Cipher.new('aes-128-gcm') -### Example: - - # Example for OpenSSL::Digest instantiation. - # bad OpenSSL::Digest::SHA256.new # good OpenSSL::Digest.new('SHA256') -### Example: - - # Example for ::Digest inherited class methods. - # bad OpenSSL::Digest::SHA256.digest('foo') diff --git a/config/contents/lint/duplicate_branch.md b/config/contents/lint/duplicate_branch.md index 710c53d1..3afdc2ea 100644 --- a/config/contents/lint/duplicate_branch.md +++ b/config/contents/lint/duplicate_branch.md @@ -10,6 +10,9 @@ the above basic literal values. With `IgnoreConstantBranches: true`, branches are not registered as offenses if they return a constant value. +With `IgnoreDuplicateElseBranch: true`, in conditionals with multiple branches, +duplicate 'else' branches are not registered as offenses. + ### Example: # bad if foo @@ -77,3 +80,13 @@ as offenses if they return a constant value. when "large" then LARGE_SIZE else MEDIUM_SIZE end + +### Example: IgnoreDuplicateElseBranch: true + # good + if foo + do_foo + elsif bar + do_bar + else + do_foo + end diff --git a/config/contents/lint/duplicate_case_condition.md b/config/contents/lint/duplicate_case_condition.md index c636f1af..cfa99a6f 100644 --- a/config/contents/lint/duplicate_case_condition.md +++ b/config/contents/lint/duplicate_case_condition.md @@ -4,7 +4,6 @@ used in case 'when' expressions. ### Example: # bad - case x when 'first' do_something @@ -12,10 +11,7 @@ used in case 'when' expressions. do_something_else end -### Example: - # good - case x when 'first' do_something diff --git a/config/contents/lint/duplicate_hash_key.md b/config/contents/lint/duplicate_hash_key.md index 520de6d7..ca65d9fe 100644 --- a/config/contents/lint/duplicate_hash_key.md +++ b/config/contents/lint/duplicate_hash_key.md @@ -6,11 +6,7 @@ This cop mirrors a warning in Ruby 2.2. ### Example: # bad - hash = { food: 'apple', food: 'orange' } -### Example: - # good - hash = { food: 'apple', other_food: 'orange' } \ No newline at end of file diff --git a/config/contents/lint/duplicate_methods.md b/config/contents/lint/duplicate_methods.md index ddff9c78..5d91d9b7 100644 --- a/config/contents/lint/duplicate_methods.md +++ b/config/contents/lint/duplicate_methods.md @@ -4,7 +4,6 @@ definitions. ### Example: # bad - def foo 1 end @@ -13,20 +12,14 @@ definitions. 2 end -### Example: - # bad - def foo 1 end alias foo bar -### Example: - # good - def foo 1 end @@ -35,10 +28,7 @@ definitions. 2 end -### Example: - # good - def foo 1 end diff --git a/config/contents/lint/duplicate_set_element.md b/config/contents/lint/duplicate_set_element.md new file mode 100644 index 00000000..4767212f --- /dev/null +++ b/config/contents/lint/duplicate_set_element.md @@ -0,0 +1,21 @@ +Checks for duplicate literal, constant, or variable elements in Set. + +### Example: + + # bad + Set[:foo, :bar, :foo] + + # good + Set[:foo, :bar] + + # bad + Set.new([:foo, :bar, :foo]) + + # good + Set.new([:foo, :bar]) + + # bad + [:foo, :bar, :foo].to_set + + # good + [:foo, :bar].to_set diff --git a/config/contents/lint/each_with_object_argument.md b/config/contents/lint/each_with_object_argument.md index bbb1fd5d..d1f06f2d 100644 --- a/config/contents/lint/each_with_object_argument.md +++ b/config/contents/lint/each_with_object_argument.md @@ -7,12 +7,8 @@ It's definitely a bug. ### Example: # bad - sum = numbers.each_with_object(0) { |e, a| a += e } -### Example: - # good - num = 0 sum = numbers.each_with_object(num) { |e, a| a += e } \ No newline at end of file diff --git a/config/contents/lint/else_layout.md b/config/contents/lint/else_layout.md index c842bf77..79a4b72c 100644 --- a/config/contents/lint/else_layout.md +++ b/config/contents/lint/else_layout.md @@ -16,8 +16,6 @@ with `elsif` and `else`, you will have to correct it manually. do_that end -### Example: - # good # This code is compatible with the bad case. It will be autocorrected like this. diff --git a/config/contents/lint/empty_ensure.md b/config/contents/lint/empty_ensure.md index 1876e431..81c42600 100644 --- a/config/contents/lint/empty_ensure.md +++ b/config/contents/lint/empty_ensure.md @@ -1,37 +1,27 @@ -Checks for empty `ensure` blocks +Checks for empty `ensure` blocks. ### Example: # bad - def some_method do_something ensure end -### Example: - # bad - begin do_something ensure end -### Example: - # good - def some_method do_something ensure do_something_else end -### Example: - # good - begin do_something ensure diff --git a/config/contents/lint/empty_interpolation.md b/config/contents/lint/empty_interpolation.md index 8535638f..fdc7d71d 100644 --- a/config/contents/lint/empty_interpolation.md +++ b/config/contents/lint/empty_interpolation.md @@ -3,11 +3,7 @@ Checks for empty interpolation. ### Example: # bad - "result is #{}" -### Example: - # good - "result is #{some_result}" \ No newline at end of file diff --git a/config/contents/lint/empty_when.md b/config/contents/lint/empty_when.md index b7ce9158..05a0c9b2 100644 --- a/config/contents/lint/empty_when.md +++ b/config/contents/lint/empty_when.md @@ -9,8 +9,6 @@ Checks for the presence of `when` branches without a body. when baz end -### Example: - # good case condition when foo diff --git a/config/contents/lint/ensure_return.md b/config/contents/lint/ensure_return.md index 47097ecb..7a8f49d8 100644 --- a/config/contents/lint/ensure_return.md +++ b/config/contents/lint/ensure_return.md @@ -8,7 +8,6 @@ If you want to rescue some (or all) exceptions, best to do it explicitly ### Example: # bad - def foo do_something ensure @@ -16,10 +15,7 @@ If you want to rescue some (or all) exceptions, best to do it explicitly return self end -### Example: - # good - def foo do_something self @@ -27,8 +23,7 @@ If you want to rescue some (or all) exceptions, best to do it explicitly cleanup end - # also good - + # good def foo begin do_something diff --git a/config/contents/lint/float_comparison.md b/config/contents/lint/float_comparison.md index aa8da4a9..47cfb0b2 100644 --- a/config/contents/lint/float_comparison.md +++ b/config/contents/lint/float_comparison.md @@ -13,7 +13,7 @@ if you perform any arithmetic operations involving precision loss. # good - using BigDecimal x.to_d == 0.1.to_d - # good - comparing against zero + # good - comparing against zero x == 0.0 x != 0.0 diff --git a/config/contents/lint/float_out_of_range.md b/config/contents/lint/float_out_of_range.md index 93c35275..27d8e6dc 100644 --- a/config/contents/lint/float_out_of_range.md +++ b/config/contents/lint/float_out_of_range.md @@ -5,11 +5,7 @@ that big. If you need a float that big, something is wrong with you. ### Example: # bad - float = 3.0e400 -### Example: - # good - float = 42.9 \ No newline at end of file diff --git a/config/contents/lint/format_parameter_mismatch.md b/config/contents/lint/format_parameter_mismatch.md index a42335cb..5e08c384 100644 --- a/config/contents/lint/format_parameter_mismatch.md +++ b/config/contents/lint/format_parameter_mismatch.md @@ -9,23 +9,13 @@ the same format string. ### Example: # bad - format('A value: %s and another: %i', a_value) -### Example: - # good - format('A value: %s and another: %i', a_value, another) -### Example: - # bad - format('Unnumbered format: %s and numbered: %2$s', a_value, another) -### Example: - # good - format('Numbered format: %1$s and numbered %2$s', a_value, another) \ No newline at end of file diff --git a/config/contents/lint/implicit_string_concatenation.md b/config/contents/lint/implicit_string_concatenation.md index 0db7d3f7..07a020ae 100644 --- a/config/contents/lint/implicit_string_concatenation.md +++ b/config/contents/lint/implicit_string_concatenation.md @@ -4,13 +4,9 @@ which are on the same line. ### Example: # bad - array = ['Item 1' 'Item 2'] -### Example: - # good - array = ['Item 1Item 2'] array = ['Item 1' + 'Item 2'] array = [ diff --git a/config/contents/lint/ineffective_access_modifier.md b/config/contents/lint/ineffective_access_modifier.md index b04033c1..659b5374 100644 --- a/config/contents/lint/ineffective_access_modifier.md +++ b/config/contents/lint/ineffective_access_modifier.md @@ -6,7 +6,6 @@ used for that. ### Example: # bad - class C private @@ -15,10 +14,7 @@ used for that. end end -### Example: - # good - class C def self.method puts 'hi' @@ -27,10 +23,7 @@ used for that. private_class_method :method end -### Example: - # good - class C class << self private diff --git a/config/contents/lint/interpolation_check.md b/config/contents/lint/interpolation_check.md index a07ddfaf..3629c4e7 100644 --- a/config/contents/lint/interpolation_check.md +++ b/config/contents/lint/interpolation_check.md @@ -10,11 +10,7 @@ the expression `foo`. ### Example: # bad - foo = 'something with #{interpolation} inside' -### Example: - # good - foo = "something with #{interpolation} inside" \ No newline at end of file diff --git a/config/contents/lint/literal_in_interpolation.md b/config/contents/lint/literal_in_interpolation.md index 54395a23..b2a55698 100644 --- a/config/contents/lint/literal_in_interpolation.md +++ b/config/contents/lint/literal_in_interpolation.md @@ -3,11 +3,7 @@ Checks for interpolated literals. ### Example: # bad - "result is #{10}" -### Example: - # good - "result is 10" \ No newline at end of file diff --git a/config/contents/lint/loop.md b/config/contents/lint/loop.md index 3fb5b9b1..ec67db34 100644 --- a/config/contents/lint/loop.md +++ b/config/contents/lint/loop.md @@ -15,17 +15,6 @@ loop body raises a `StopIteration` exception (which `Kernel#loop` rescues). do_something end while some_condition -### Example: - - # bad - - # using until - begin - do_something - end until some_condition - -### Example: - # good # while replacement @@ -34,7 +23,12 @@ loop body raises a `StopIteration` exception (which `Kernel#loop` rescues). break unless some_condition end -### Example: + # bad + + # using until + begin + do_something + end until some_condition # good diff --git a/config/contents/lint/nested_method_definition.md b/config/contents/lint/nested_method_definition.md index e69ae3de..c742139c 100644 --- a/config/contents/lint/nested_method_definition.md +++ b/config/contents/lint/nested_method_definition.md @@ -12,8 +12,6 @@ Checks for nested method definitions. end end -### Example: - # good def foo @@ -21,8 +19,6 @@ Checks for nested method definitions. bar.call end -### Example: - # good # `class_eval`, `instance_eval`, `module_eval`, `class_exec`, `instance_exec`, and @@ -42,8 +38,6 @@ Checks for nested method definitions. end end -### Example: - # good def foo diff --git a/config/contents/lint/next_without_accumulator.md b/config/contents/lint/next_without_accumulator.md index b3226b11..725007e9 100644 --- a/config/contents/lint/next_without_accumulator.md +++ b/config/contents/lint/next_without_accumulator.md @@ -3,16 +3,12 @@ Don't omit the accumulator when calling `next` in a `reduce` block. ### Example: # bad - result = (1..4).reduce(0) do |acc, i| next if i.odd? acc + i end -### Example: - # good - result = (1..4).reduce(0) do |acc, i| next acc if i.odd? acc + i diff --git a/config/contents/lint/no_return_in_begin_end_blocks.md b/config/contents/lint/no_return_in_begin_end_blocks.md index 40bc70cc..7bb08b03 100644 --- a/config/contents/lint/no_return_in_begin_end_blocks.md +++ b/config/contents/lint/no_return_in_begin_end_blocks.md @@ -6,17 +6,13 @@ method, possibly leading to unexpected behavior. ### Example: # bad - @some_variable ||= begin return some_value if some_condition_is_met do_something end -### Example: - # good - @some_variable ||= begin if some_condition_is_met some_value @@ -26,7 +22,6 @@ method, possibly leading to unexpected behavior. end # good - some_variable = if some_condition_is_met return if another_condition_is_met diff --git a/config/contents/lint/percent_string_array.md b/config/contents/lint/percent_string_array.md index 5e959679..5bef2e6c 100644 --- a/config/contents/lint/percent_string_array.md +++ b/config/contents/lint/percent_string_array.md @@ -17,11 +17,7 @@ and that might have been done purposely. ### Example: # bad - %w('foo', "bar") -### Example: - # good - %w(foo bar) \ No newline at end of file diff --git a/config/contents/lint/percent_symbol_array.md b/config/contents/lint/percent_symbol_array.md index 2177bd37..fa981b70 100644 --- a/config/contents/lint/percent_symbol_array.md +++ b/config/contents/lint/percent_symbol_array.md @@ -7,11 +7,7 @@ rather than meant to be part of the resulting symbols. ### Example: # bad - %i(:foo, :bar) -### Example: - # good - %i(foo bar) \ No newline at end of file diff --git a/config/contents/lint/rand_one.md b/config/contents/lint/rand_one.md index b729d9d9..223620ad 100644 --- a/config/contents/lint/rand_one.md +++ b/config/contents/lint/rand_one.md @@ -4,14 +4,10 @@ Such calls always return `0`. ### Example: # bad - rand 1 Kernel.rand(-1) rand 1.0 rand(-1.0) -### Example: - # good - 0 # just use 0 instead \ No newline at end of file diff --git a/config/contents/lint/redundant_cop_enable_directive.md b/config/contents/lint/redundant_cop_enable_directive.md index 875b52e4..fd6646d0 100644 --- a/config/contents/lint/redundant_cop_enable_directive.md +++ b/config/contents/lint/redundant_cop_enable_directive.md @@ -3,14 +3,16 @@ removed. When comment enables all cops at once `rubocop:enable all` that cop checks whether any cop was actually enabled. + ### Example: + # bad foo = 1 # rubocop:enable Layout/LineLength # good foo = 1 -### Example: + # bad # rubocop:disable Style/StringLiterals foo = "1" diff --git a/config/contents/lint/redundant_splat_expansion.md b/config/contents/lint/redundant_splat_expansion.md index 5a610991..c6e043f4 100644 --- a/config/contents/lint/redundant_splat_expansion.md +++ b/config/contents/lint/redundant_splat_expansion.md @@ -1,4 +1,4 @@ -Checks for unneeded usages of splat expansion +Checks for unneeded usages of splat expansion. ### Example: diff --git a/config/contents/lint/redundant_string_coercion.md b/config/contents/lint/redundant_string_coercion.md index 793ab5ea..afa1b33b 100644 --- a/config/contents/lint/redundant_string_coercion.md +++ b/config/contents/lint/redundant_string_coercion.md @@ -4,16 +4,12 @@ which is redundant. ### Example: # bad - "result is #{something.to_s}" print something.to_s puts something.to_s warn something.to_s -### Example: - # good - "result is #{something}" print something puts something diff --git a/config/contents/lint/require_parentheses.md b/config/contents/lint/require_parentheses.md index bf196364..484fa843 100644 --- a/config/contents/lint/require_parentheses.md +++ b/config/contents/lint/require_parentheses.md @@ -10,15 +10,11 @@ an operand of &&/||. ### Example: # bad - if day.is? :tuesday && month == :jan # ... end -### Example: - # good - if day.is?(:tuesday) && month == :jan # ... end \ No newline at end of file diff --git a/config/contents/lint/rescue_exception.md b/config/contents/lint/rescue_exception.md index ec975aff..21413b54 100644 --- a/config/contents/lint/rescue_exception.md +++ b/config/contents/lint/rescue_exception.md @@ -3,17 +3,13 @@ Checks for `rescue` blocks targeting the Exception class. ### Example: # bad - begin do_something rescue Exception handle_exception end -### Example: - # good - begin do_something rescue ArgumentError diff --git a/config/contents/lint/return_in_void_context.md b/config/contents/lint/return_in_void_context.md index eb9fd809..5df54c2d 100644 --- a/config/contents/lint/return_in_void_context.md +++ b/config/contents/lint/return_in_void_context.md @@ -14,8 +14,6 @@ where the value will be ignored. (initialize and setter methods) return 42 end -### Example: - # good def initialize foo diff --git a/config/contents/lint/safe_navigation_chain.md b/config/contents/lint/safe_navigation_chain.md index 6feb81d2..906f1b82 100644 --- a/config/contents/lint/safe_navigation_chain.md +++ b/config/contents/lint/safe_navigation_chain.md @@ -7,14 +7,10 @@ This cop checks for the problem outlined above. ### Example: # bad - x&.foo.bar x&.foo + bar x&.foo[bar] -### Example: - # good - x&.foo&.bar x&.foo || bar \ No newline at end of file diff --git a/config/contents/lint/safe_navigation_consistency.md b/config/contents/lint/safe_navigation_consistency.md index 7d5e51bd..a7e2f331 100644 --- a/config/contents/lint/safe_navigation_consistency.md +++ b/config/contents/lint/safe_navigation_consistency.md @@ -1,22 +1,34 @@ -Check to make sure that if safe navigation is used for a method -call in an `&&` or `||` condition that safe navigation is used for all -method calls on that same object. +Check to make sure that if safe navigation is used in an `&&` or `||` condition, +consistent and appropriate safe navigation, without excess or deficiency, +is used for all method calls on the same object. ### Example: # bad - foo&.bar && foo.baz + foo&.bar && foo&.baz - # bad - foo.bar || foo&.baz + # good + foo&.bar && foo.baz # bad - foo&.bar && (foobar.baz || foo.baz) + foo.bar && foo&.baz # good foo.bar && foo.baz + # bad + foo&.bar || foo.baz + # good foo&.bar || foo&.baz + # bad + foo.bar || foo&.baz + # good + foo.bar || foo.baz + + # bad foo&.bar && (foobar.baz || foo&.baz) + + # good + foo&.bar && (foobar.baz || foo.baz) diff --git a/config/contents/lint/shadowing_outer_local_variable.md b/config/contents/lint/shadowing_outer_local_variable.md index 04353df3..6c966e1c 100644 --- a/config/contents/lint/shadowing_outer_local_variable.md +++ b/config/contents/lint/shadowing_outer_local_variable.md @@ -7,16 +7,15 @@ NOTE: Shadowing of variables in block passed to `Ractor.new` is allowed because `Ractor` should not access outer variables. eg. following style is encouraged: - ```ruby - worker_id, pipe = env - Ractor.new(worker_id, pipe) do |worker_id, pipe| - end - ``` +```ruby +worker_id, pipe = env +Ractor.new(worker_id, pipe) do |worker_id, pipe| +end +``` ### Example: # bad - def some_method foo = 1 @@ -25,10 +24,7 @@ eg. following style is encouraged: end end -### Example: - # good - def some_method foo = 1 diff --git a/config/contents/lint/unescaped_bracket_in_regexp.md b/config/contents/lint/unescaped_bracket_in_regexp.md new file mode 100644 index 00000000..04b6be13 --- /dev/null +++ b/config/contents/lint/unescaped_bracket_in_regexp.md @@ -0,0 +1,22 @@ +Checks for Regexpes (both literals and via `Regexp.new` / `Regexp.compile`) +that contain unescaped `]` characters. + +It emulates the following Ruby warning: + +```ruby +$ ruby -e '/abc]123/' +-e:1: warning: regular expression has ']' without escape: /abc]123/ +``` + +### Example: + # bad + /abc]123/ + %r{abc]123} + Regexp.new('abc]123') + Regexp.compile('abc]123') + + # good + /abc\]123/ + %r{abc\]123} + Regexp.new('abc\]123') + Regexp.compile('abc\]123') diff --git a/config/contents/lint/unified_integer.md b/config/contents/lint/unified_integer.md index 71005cd9..959bcacf 100644 --- a/config/contents/lint/unified_integer.md +++ b/config/contents/lint/unified_integer.md @@ -3,12 +3,8 @@ Checks for using Fixnum or Bignum constant. ### Example: # bad - 1.is_a?(Fixnum) 1.is_a?(Bignum) -### Example: - # good - 1.is_a?(Integer) \ No newline at end of file diff --git a/config/contents/lint/unreachable_code.md b/config/contents/lint/unreachable_code.md index 3af20b6b..182cb0fd 100644 --- a/config/contents/lint/unreachable_code.md +++ b/config/contents/lint/unreachable_code.md @@ -5,14 +5,12 @@ statement in non-final position in `begin` (implicit) blocks. ### Example: # bad - def some_method return do_something end # bad - def some_method if cond return @@ -22,10 +20,7 @@ statement in non-final position in `begin` (implicit) blocks. do_something end -### Example: - # good - def some_method do_something end \ No newline at end of file diff --git a/config/contents/lint/uri_regexp.md b/config/contents/lint/uri_regexp.md index dfd29c3b..318b7c44 100644 --- a/config/contents/lint/uri_regexp.md +++ b/config/contents/lint/uri_regexp.md @@ -1,9 +1,21 @@ -Identifies places where `URI.regexp` is obsolete and should -not be used. Instead, use `URI::DEFAULT_PARSER.make_regexp`. +Identifies places where `URI.regexp` is obsolete and should not be used. + +For Ruby 3.3 or lower, use `URI::DEFAULT_PARSER.make_regexp`. +For Ruby 3.4 or higher, use `URI::RFC2396_PARSER.make_regexp`. + +NOTE: If you need to support both Ruby 3.3 and lower as well as Ruby 3.4 and higher, +consider manually changing the code as follows: + +```ruby +defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER +``` ### Example: # bad URI.regexp('http://example.com') - # good + # good - Ruby 3.3 or lower URI::DEFAULT_PARSER.make_regexp('http://example.com') + + # good - Ruby 3.4 or higher + URI::RFC2396_PARSER.make_regexp('http://example.com') diff --git a/config/contents/lint/useless_assignment.md b/config/contents/lint/useless_assignment.md index 717e4099..eb80bc3c 100644 --- a/config/contents/lint/useless_assignment.md +++ b/config/contents/lint/useless_assignment.md @@ -10,29 +10,23 @@ 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. - -### Safety: - -This cop's autocorrection is unsafe because removing assignment from +This cop's autocorrection avoids cases like `a ||= 1` because removing assignment from operator assignment can cause NameError if this assignment has been used to declare -local variable. For example, replacing `a ||= 1` to `a || 1` may cause +a local variable. For example, replacing `a ||= 1` with `a || 1` may cause "undefined local variable or method `a' for main:Object (NameError)". +NOTE: Given the assignment `foo = 1, bar = 2`, removing unused variables +can lead to a syntax error, so this case is not autocorrected. + ### Example: # bad - def some_method some_var = 1 do_something end -### Example: - # good - def some_method some_var = 1 do_something(some_var) diff --git a/config/contents/lint/useless_else_without_rescue.md b/config/contents/lint/useless_else_without_rescue.md index 12fdf021..9b63a28d 100644 --- a/config/contents/lint/useless_else_without_rescue.md +++ b/config/contents/lint/useless_else_without_rescue.md @@ -5,17 +5,13 @@ NOTE: This syntax is no longer valid on Ruby 2.6 or higher. ### Example: # bad - begin do_something else do_something_else # This will never be run. end -### Example: - # good - begin do_something rescue diff --git a/config/contents/lint/useless_numeric_operation.md b/config/contents/lint/useless_numeric_operation.md new file mode 100644 index 00000000..ae33c163 --- /dev/null +++ b/config/contents/lint/useless_numeric_operation.md @@ -0,0 +1,25 @@ +Certain numeric operations have no impact, being: +Adding or subtracting 0, multiplying or dividing by 1 or raising to the power of 1. +These are probably leftover from debugging, or are mistakes. + +### Example: + + # bad + x + 0 + x - 0 + x * 1 + x / 1 + x ** 1 + + # good + x + + # bad + x += 0 + x -= 0 + x *= 1 + x /= 1 + x **= 1 + + # good + x = x diff --git a/config/contents/lint/useless_setter_call.md b/config/contents/lint/useless_setter_call.md index f4a7d328..15191037 100644 --- a/config/contents/lint/useless_setter_call.md +++ b/config/contents/lint/useless_setter_call.md @@ -13,16 +13,12 @@ return value will be changed. ### Example: # bad - def something x = Something.new x.attr = 5 end -### Example: - # good - def something x = Something.new x.attr = 5 diff --git a/config/contents/metrics/block_length.md b/config/contents/metrics/block_length.md index 8f18efe3..1098e051 100644 --- a/config/contents/metrics/block_length.md +++ b/config/contents/metrics/block_length.md @@ -4,8 +4,9 @@ The maximum allowed length is configurable. The cop can be configured to ignore blocks passed to certain methods. 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. + +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. @@ -13,7 +14,7 @@ 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. -### Example: CountAsOne: ['array', 'heredoc', 'method_call'] +### Example: CountAsOne: ['array', 'hash', 'heredoc', 'method_call'] something do array = [ # +1 @@ -21,7 +22,7 @@ instead. By default, there are no methods to allowed. 2 ] - hash = { # +3 + hash = { # +1 key: 'value' } @@ -34,4 +35,4 @@ instead. By default, there are no methods to allowed. 1, 2 ) - end # 6 points + end # 4 points diff --git a/config/contents/metrics/block_nesting.md b/config/contents/metrics/block_nesting.md index 413c93b4..08282195 100644 --- a/config/contents/metrics/block_nesting.md +++ b/config/contents/metrics/block_nesting.md @@ -1,8 +1,8 @@ -Checks for excessive nesting of conditional and looping -constructs. +Checks for excessive nesting of conditional and looping constructs. -You can configure if blocks are considered using the `CountBlocks` -option. When set to `false` (the default) blocks are not counted -towards the nesting level. Set to `true` to count blocks as well. +You can configure if blocks are considered using the `CountBlocks` and `CountModifierForms` +options. When both are set to `false` (the default) blocks and modifier forms are not +counted towards the nesting level. Set them to `true` to include these in the nesting level +calculation as well. The maximum level of nesting allowed is configurable. \ No newline at end of file diff --git a/config/contents/metrics/class_length.md b/config/contents/metrics/class_length.md index bb2823b0..e91bb50d 100644 --- a/config/contents/metrics/class_length.md +++ b/config/contents/metrics/class_length.md @@ -3,12 +3,13 @@ Comment lines can optionally be ignored. The maximum allowed length is configurable. 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. + +Available are: 'array', 'hash', 'heredoc', and 'method_call'. +Each construct will be counted as one line regardless of its actual size. NOTE: This cop also applies for `Struct` definitions. -### Example: CountAsOne: ['array', 'heredoc', 'method_call'] +### Example: CountAsOne: ['array', 'hash', 'heredoc', 'method_call'] class Foo ARRAY = [ # +1 @@ -16,7 +17,7 @@ NOTE: This cop also applies for `Struct` definitions. 2 ] - HASH = { # +3 + HASH = { # +1 key: 'value' } @@ -29,4 +30,4 @@ NOTE: This cop also applies for `Struct` definitions. 1, 2 ) - end # 6 points + end # 4 points diff --git a/config/contents/metrics/cyclomatic_complexity.md b/config/contents/metrics/cyclomatic_complexity.md index 88bd324a..1db99e95 100644 --- a/config/contents/metrics/cyclomatic_complexity.md +++ b/config/contents/metrics/cyclomatic_complexity.md @@ -9,11 +9,14 @@ operator (or keyword and) can be converted to a nested if statement, and ||/or is shorthand for a sequence of ifs, so they also add one. Loops can be said to have an exit condition, so they add one. Blocks that are calls to builtin iteration methods -(e.g. `ary.map{...}) also add one, others are ignored. +(e.g. `ary.map{...}`) also add one, others are ignored. + +### Example: def each_child_node(*types) # count begins: 1 unless block_given? # unless: +1 return to_enum(__method__, *types) + end children.each do |child| # each{}: +1 next unless child.is_a?(Node) # unless: +1 diff --git a/config/contents/metrics/method_length.md b/config/contents/metrics/method_length.md index 281adfee..af114667 100644 --- a/config/contents/metrics/method_length.md +++ b/config/contents/metrics/method_length.md @@ -3,15 +3,16 @@ Comment lines can optionally be allowed. The maximum allowed length is configurable. 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. + +Available are: 'array', 'hash', 'heredoc', and 'method_call'. +Each construct will be counted as one line regardless of its actual size. NOTE: The `ExcludedMethods` and `IgnoredMethods` configuration is deprecated and only kept for backwards compatibility. Please use `AllowedMethods` and `AllowedPatterns` instead. By default, there are no methods to allowed. -### Example: CountAsOne: ['array', 'heredoc', 'method_call'] +### Example: CountAsOne: ['array', 'hash', 'heredoc', 'method_call'] def m array = [ # +1 @@ -19,7 +20,7 @@ By default, there are no methods to allowed. 2 ] - hash = { # +3 + hash = { # +1 key: 'value' } @@ -32,4 +33,4 @@ By default, there are no methods to allowed. 1, 2 ) - end # 6 points + end # 4 points diff --git a/config/contents/metrics/module_length.md b/config/contents/metrics/module_length.md index 653aecee..2cb7f667 100644 --- a/config/contents/metrics/module_length.md +++ b/config/contents/metrics/module_length.md @@ -3,10 +3,11 @@ Comment lines can optionally be ignored. The maximum allowed length is configurable. 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. -### Example: CountAsOne: ['array', 'heredoc', 'method_call'] +Available are: 'array', 'hash', 'heredoc', and 'method_call'. +Each construct will be counted as one line regardless of its actual size. + +### Example: CountAsOne: ['array', 'hash', 'heredoc', 'method_call'] module M ARRAY = [ # +1 @@ -14,7 +15,7 @@ will be counted as one line regardless of its actual size. 2 ] - HASH = { # +3 + HASH = { # +1 key: 'value' } @@ -27,4 +28,4 @@ will be counted as one line regardless of its actual size. 1, 2 ) - end # 6 points + end # 4 points diff --git a/config/contents/naming/predicate_name.md b/config/contents/naming/predicate_name.md index b3454b75..616b4c70 100644 --- a/config/contents/naming/predicate_name.md +++ b/config/contents/naming/predicate_name.md @@ -1,52 +1,68 @@ -Checks that predicate methods names end with a question mark and +Checks that predicate method names end with a question mark and do not start with a forbidden prefix. -A method is determined to be a predicate method if its name starts -with one of the prefixes defined in the `NamePrefix` configuration. -You can change what prefixes are considered by changing this option. -Any method name that starts with one of these prefixes is required by -the cop to end with a `?`. Other methods can be allowed by adding to -the `AllowedMethods` configuration. +A method is determined to be a predicate method if its name starts with +one of the prefixes listed in the `NamePrefix` configuration. The list +defaults to `is_`, `has_`, and `have_` but may be overridden. -NOTE: The `is_a?` method is allowed by default. +Predicate methods must end with a question mark. -If `ForbiddenPrefixes` is set, methods that start with the configured -prefixes will not be allowed and will be removed by autocorrection. +When `ForbiddenPrefixes` is also set (as it is by default), predicate +methods which begin with a forbidden prefix are not allowed, even if +they end with a `?`. These methods should be changed to remove the +prefix. -In other words, if `ForbiddenPrefixes` is empty, a method named `is_foo` -will register an offense only due to the lack of question mark (and will be -autocorrected to `is_foo?`). If `ForbiddenPrefixes` contains `is_`, -`is_foo` will register an offense both because the ? is missing and because of -the `is_` prefix, and will be corrected to `foo?`. - -NOTE: `ForbiddenPrefixes` is only applied to prefixes in `NamePrefix`; -a prefix in the former but not the latter will not be considered by -this cop. - -### Example: +### Example: NamePrefix: ['is_', 'has_', 'have_'] (default) # bad def is_even(value) end - def is_even?(value) + # When ForbiddenPrefixes: ['is_', 'has_', 'have_'] (default) + # good + def even?(value) end + # When ForbiddenPrefixes: [] # good - def even?(value) + def is_even?(value) end +### Example: NamePrefix: ['seems_to_be_'] # bad - def has_value + def seems_to_be_even(value) end - def has_value? + # When ForbiddenPrefixes: ['seems_to_be_'] + # good + def even?(value) end + # When ForbiddenPrefixes: [] # good - def value? + def seems_to_be_even?(value) end ### Example: AllowedMethods: ['is_a?'] (default) + # Despite starting with the `is_` prefix, this method is allowed # good def is_a?(value) end + +### Example: AllowedMethods: ['is_even?'] + # good + def is_even?(value) + end + +### Example: MethodDefinitionMacros: ['define_method', 'define_singleton_method'] (default) + # bad + define_method(:is_even) { |value| } + + # good + define_method(:even?) { |value| } + +### Example: MethodDefinitionMacros: ['def_node_matcher'] + # bad + def_node_matcher(:is_even) { |value| } + + # good + def_node_matcher(:even?) { |value| } diff --git a/config/contents/style/access_modifier_declarations.md b/config/contents/style/access_modifier_declarations.md index 0811a77b..eec6b704 100644 --- a/config/contents/style/access_modifier_declarations.md +++ b/config/contents/style/access_modifier_declarations.md @@ -64,6 +64,8 @@ the group access modifier. class Foo private :bar, :baz + private *%i[qux quux] + private *METHOD_NAMES end @@ -72,6 +74,8 @@ the group access modifier. class Foo private :bar, :baz + private *%i[qux quux] + private *METHOD_NAMES end diff --git a/config/contents/style/accessor_grouping.md b/config/contents/style/accessor_grouping.md index bb8c0c81..30fba283 100644 --- a/config/contents/style/accessor_grouping.md +++ b/config/contents/style/accessor_grouping.md @@ -5,6 +5,9 @@ but it can be configured to enforce separating them in multiple declarations. NOTE: If there is a method call before the accessor method it is always allowed as it might be intended like Sorbet. +NOTE: If there is a RBS::Inline annotation comment just after the accessor method +it is always allowed. + ### Example: EnforcedStyle: grouped (default) # bad class Foo diff --git a/config/contents/style/ambiguous_endless_method_definition.md b/config/contents/style/ambiguous_endless_method_definition.md new file mode 100644 index 00000000..012d60f1 --- /dev/null +++ b/config/contents/style/ambiguous_endless_method_definition.md @@ -0,0 +1,23 @@ +Looks for endless methods inside operations of lower precedence (`and`, `or`, and +modifier forms of `if`, `unless`, `while`, `until`) that are ambiguous due to +lack of parentheses. This may lead to unexpected behavior as the code may appear +to use these keywords as part of the method but in fact they modify +the method definition itself. + +In these cases, using a normal method definition is more clear. + +### Example: + + # bad + def foo = true if bar + + # good - using a non-endless method is more explicit + def foo + true + end if bar + + # ok - method body is explicit + def foo = (true if bar) + + # ok - method definition is explicit + (def foo = true) if bar \ No newline at end of file diff --git a/config/contents/style/bitwise_predicate.md b/config/contents/style/bitwise_predicate.md new file mode 100644 index 00000000..2f47d517 --- /dev/null +++ b/config/contents/style/bitwise_predicate.md @@ -0,0 +1,26 @@ +Prefer bitwise predicate methods over direct comparison operations. + +### Safety: + +This cop is unsafe, as it can produce false positives if the receiver +is not an `Integer` object. + +### Example: + + # bad - checks any set bits + (variable & flags).positive? + + # good + variable.anybits?(flags) + + # bad - checks all set bits + (variable & flags) == flags + + # good + variable.allbits?(flags) + + # bad - checks no set bits + (variable & flags).zero? + + # good + variable.nobits?(flags) diff --git a/config/contents/style/collection_compact.md b/config/contents/style/collection_compact.md index 666584ad..81cdab63 100644 --- a/config/contents/style/collection_compact.md +++ b/config/contents/style/collection_compact.md @@ -17,6 +17,7 @@ when the receiver is a hash object. array.reject(&:nil?) array.reject { |e| e.nil? } array.select { |e| !e.nil? } + array.filter { |e| !e.nil? } array.grep_v(nil) array.grep_v(NilClass) @@ -25,10 +26,9 @@ when the receiver is a hash object. # bad hash.reject!(&:nil?) - array.delete_if(&:nil?) hash.reject! { |k, v| v.nil? } - array.delete_if { |e| e.nil? } hash.select! { |k, v| !v.nil? } + hash.filter! { |k, v| !v.nil? } # good hash.compact! diff --git a/config/contents/style/combinable_defined.md b/config/contents/style/combinable_defined.md new file mode 100644 index 00000000..2d8c41a2 --- /dev/null +++ b/config/contents/style/combinable_defined.md @@ -0,0 +1,18 @@ +Checks for multiple `defined?` calls joined by `&&` that can be combined +into a single `defined?`. + +When checking that a nested constant or chained method is defined, it is +not necessary to check each ancestor or component of the chain. + +### Example: + # bad + defined?(Foo) && defined?(Foo::Bar) && defined?(Foo::Bar::Baz) + + # good + defined?(Foo::Bar::Baz) + + # bad + defined?(foo) && defined?(foo.bar) && defined?(foo.bar.baz) + + # good + defined?(foo.bar.baz) \ No newline at end of file diff --git a/config/contents/style/combinable_loops.md b/config/contents/style/combinable_loops.md index 6f1c437e..8e78f060 100644 --- a/config/contents/style/combinable_loops.md +++ b/config/contents/style/combinable_loops.md @@ -2,6 +2,9 @@ Checks for places where multiple consecutive loops over the same data can be combined into a single loop. It is very likely that combining them will make the code more efficient and more concise. +NOTE: Autocorrection is not applied when the block variable names differ in separate loops, +as it is impossible to determine which variable name should be prioritized. + ### Safety: The cop is unsafe, because the first loop might modify state that the diff --git a/config/contents/style/commented_keyword.md b/config/contents/style/commented_keyword.md index 0b1b9c1d..d097e3c0 100644 --- a/config/contents/style/commented_keyword.md +++ b/config/contents/style/commented_keyword.md @@ -3,7 +3,7 @@ These keywords are: `class`, `module`, `def`, `begin`, `end`. Note that some comments (`:nodoc:`, `:yields:`, `rubocop:disable` and `rubocop:todo`) -are allowed. +and RBS::Inline annotation comments are allowed. Autocorrection removes comments from `end` keyword and keeps comments for `class`, `module`, `def` and `begin` above the keyword. diff --git a/config/contents/style/def_with_parentheses.md b/config/contents/style/def_with_parentheses.md index eb2f930f..d4f5569a 100644 --- a/config/contents/style/def_with_parentheses.md +++ b/config/contents/style/def_with_parentheses.md @@ -23,8 +23,6 @@ class/singleton methods are checked. # good (without parentheses it's a syntax error) def foo() do_something end -### Example: - # bad def Baz.foo() do_something diff --git a/config/contents/style/each_for_simple_loop.md b/config/contents/style/each_for_simple_loop.md index 7a8523de..ba7a424d 100644 --- a/config/contents/style/each_for_simple_loop.md +++ b/config/contents/style/each_for_simple_loop.md @@ -11,7 +11,6 @@ This check only applies if the block takes no parameters. # good 5.times { } -### Example: # bad (0...10).each {} diff --git a/config/contents/style/empty_literal.md b/config/contents/style/empty_literal.md index d1ee0d5b..1cc5fb67 100644 --- a/config/contents/style/empty_literal.md +++ b/config/contents/style/empty_literal.md @@ -4,7 +4,9 @@ would be a literal, like an empty array, hash, or string. ### Example: # bad a = Array.new + a = Array[] h = Hash.new + h = Hash[] s = String.new # good diff --git a/config/contents/style/eval_with_location.md b/config/contents/style/eval_with_location.md index f441417b..fff337a1 100644 --- a/config/contents/style/eval_with_location.md +++ b/config/contents/style/eval_with_location.md @@ -12,6 +12,17 @@ values. However, if `eval` is called without a binding argument, the cop will not attempt to automatically add a binding, or add filename and line values. +NOTE: This cop works only when a string literal is given as a code string. +No offense is reported if a string variable is given as below: + +```ruby +code = <<-RUBY + def do_something + end +RUBY +eval code # not checked. +``` + ### Example: # bad eval <<-RUBY @@ -36,14 +47,3 @@ line values. def do_something end RUBY - -This cop works only when a string literal is given as a code string. -No offense is reported if a string variable is given as below: - -### Example: - # not checked - code = <<-RUBY - def do_something - end - RUBY - eval code diff --git a/config/contents/style/file_read.md b/config/contents/style/file_read.md index 0a6dcf51..af38459b 100644 --- a/config/contents/style/file_read.md +++ b/config/contents/style/file_read.md @@ -1,8 +1,7 @@ Favor `File.(bin)read` convenience methods. ### Example: - ## text mode - # bad + # bad - text mode File.open(filename).read File.open(filename, &:read) File.open(filename) { |f| f.read } @@ -18,9 +17,7 @@ Favor `File.(bin)read` convenience methods. # good File.read(filename) -### Example: - ## binary mode - # bad + # bad - binary mode File.open(filename, 'rb').read File.open(filename, 'rb', &:read) File.open(filename, 'rb') do |f| diff --git a/config/contents/style/file_write.md b/config/contents/style/file_write.md index ceaf6c9f..679ff58b 100644 --- a/config/contents/style/file_write.md +++ b/config/contents/style/file_write.md @@ -11,8 +11,7 @@ end ``` ### Example: - ## text mode - # bad + # bad - text mode File.open(filename, 'w').write(content) File.open(filename, 'w') do |f| f.write(content) @@ -21,9 +20,7 @@ end # good File.write(filename, content) -### Example: - ## binary mode - # bad + # bad - binary mode File.open(filename, 'wb').write(content) File.open(filename, 'wb') do |f| f.write(content) diff --git a/config/contents/style/format_string_token.md b/config/contents/style/format_string_token.md index 132e186e..b913abc1 100644 --- a/config/contents/style/format_string_token.md +++ b/config/contents/style/format_string_token.md @@ -6,8 +6,8 @@ which are passed as arguments to those methods: The reason is that _unannotated_ format is very similar to encoded URLs or Date/Time formatting strings. -This cop can be customized allowed methods with `AllowedMethods`. -By default, there are no methods to allowed. +This cop's allowed methods can be customized with `AllowedMethods`. +By default, there are no allowed methods. ### Example: EnforcedStyle: annotated (default) diff --git a/config/contents/style/hash_except.md b/config/contents/style/hash_except.md index ab9b2cf1..3f77d5bf 100644 --- a/config/contents/style/hash_except.md +++ b/config/contents/style/hash_except.md @@ -19,9 +19,9 @@ is a `Hash` or responds to the replacement method. {foo: 1, bar: 2, baz: 3}.reject {|k, v| k == :bar } {foo: 1, bar: 2, baz: 3}.select {|k, v| k != :bar } {foo: 1, bar: 2, baz: 3}.filter {|k, v| k != :bar } - {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[foo bar].include?(k) } - {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[foo bar].include?(k) } - {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[foo bar].include?(k) } + {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].include?(k) } + {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].include?(k) } + {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[bar].include?(k) } # good {foo: 1, bar: 2, baz: 3}.except(:bar) diff --git a/config/contents/style/hash_syntax.md b/config/contents/style/hash_syntax.md index 778d5b74..7ab0a7cc 100644 --- a/config/contents/style/hash_syntax.md +++ b/config/contents/style/hash_syntax.md @@ -63,7 +63,7 @@ The supported styles are: {a: 1, b: 2} {:c => 3, 'd' => 4} -### Example: EnforcedShorthandSyntax: always (default) +### Example: EnforcedShorthandSyntax: always # bad {foo: foo, bar: bar} @@ -79,7 +79,7 @@ The supported styles are: # good {foo: foo, bar: bar} -### Example: EnforcedShorthandSyntax: either +### Example: EnforcedShorthandSyntax: either (default) # good {foo: foo, bar: bar} diff --git a/config/contents/style/if_with_boolean_literal_branches.md b/config/contents/style/if_with_boolean_literal_branches.md index 14cb25a4..8ce1c191 100644 --- a/config/contents/style/if_with_boolean_literal_branches.md +++ b/config/contents/style/if_with_boolean_literal_branches.md @@ -39,7 +39,6 @@ will return a boolean value. Those methods can be allowed with `AllowedMethods` # good foo == bar -### Example: # bad if foo.do_something? true diff --git a/config/contents/style/keyword_arguments_merging.md b/config/contents/style/keyword_arguments_merging.md new file mode 100644 index 00000000..6e8ca3c9 --- /dev/null +++ b/config/contents/style/keyword_arguments_merging.md @@ -0,0 +1,14 @@ +When passing an existing hash as keyword arguments, provide additional arguments +directly rather than using `merge`. + +Providing arguments directly is more performant, than using `merge`, and +also leads to a shorter and simpler code. + +### Example: + # bad + some_method(**opts.merge(foo: true)) + some_method(**opts.merge(other_opts)) + + # good + some_method(**opts, foo: true) + some_method(**opts, **other_opts) diff --git a/config/contents/style/map_compact_with_conditional_block.md b/config/contents/style/map_compact_with_conditional_block.md index dad637ce..5c18dc5b 100644 --- a/config/contents/style/map_compact_with_conditional_block.md +++ b/config/contents/style/map_compact_with_conditional_block.md @@ -1,10 +1,14 @@ Prefer `select` or `reject` over `map { ... }.compact`. +This cop also handles `filter_map { ... }`, similar to `map { ... }.compact`. ### Example: # bad array.map { |e| some_condition? ? e : next }.compact + # bad + array.filter_map { |e| some_condition? ? e : next } + # bad array.map do |e| if some_condition? diff --git a/config/contents/style/map_into_array.md b/config/contents/style/map_into_array.md index d52f2ae9..b56797d4 100644 --- a/config/contents/style/map_into_array.md +++ b/config/contents/style/map_into_array.md @@ -8,8 +8,10 @@ NOTE: The return value of `Enumerable#each` is `self`, whereas the return value of `Enumerable#map` is an `Array`. They are not autocorrected when a return value could be used because these types differ. -NOTE: It only detects when the mapping destination is a local variable -initialized as an empty array and referred to only by the pushing operation. +NOTE: It only detects when the mapping destination is either: +* a local variable initialized as an empty array and referred to only by the +pushing operation; +* or, if it is the single block argument to a `[].tap` block. This is because, if not, it's challenging to statically guarantee that the mapping destination variable remains an empty array: @@ -37,6 +39,14 @@ with a block, not all objects that have a `map` method return an array # good dest = src.map { |e| e * 2 } + # bad + [].tap do |dest| + src.each { |e| dest << e * 2 } + end + + # good + dest = src.map { |e| e * 2 } + # good - contains another operation dest = [] src.each { |e| dest << e * 2; puts e } diff --git a/config/contents/style/method_call_with_args_parentheses.md b/config/contents/style/method_call_with_args_parentheses.md index 94361dbf..817774d3 100644 --- a/config/contents/style/method_call_with_args_parentheses.md +++ b/config/contents/style/method_call_with_args_parentheses.md @@ -1,5 +1,5 @@ Enforces the presence (default) or absence of parentheses in -method calls containing parameters. +method calls containing arguments. In the default style (require_parentheses), macro methods are allowed. Additional methods can be added to the `AllowedMethods` or diff --git a/config/contents/style/method_call_without_args_parentheses.md b/config/contents/style/method_call_without_args_parentheses.md index a2ed9c9a..e6feef93 100644 --- a/config/contents/style/method_call_without_args_parentheses.md +++ b/config/contents/style/method_call_without_args_parentheses.md @@ -1,7 +1,7 @@ Checks for unwanted parentheses in parameterless method calls. -This cop can be customized allowed methods with `AllowedMethods`. -By default, there are no methods to allowed. +This cop's allowed methods can be customized with `AllowedMethods`. +By default, there are no allowed methods. NOTE: This cop allows the use of `it()` without arguments in blocks, as in `0.times { it() }`, following `Lint/ItWithoutArgumentsInBlock` cop. diff --git a/config/contents/style/numeric_predicate.md b/config/contents/style/numeric_predicate.md index 50902e37..c73b731d 100644 --- a/config/contents/style/numeric_predicate.md +++ b/config/contents/style/numeric_predicate.md @@ -3,8 +3,8 @@ Checks for usage of comparison operators (`==`, These can be replaced by their respective predicate methods. This cop can also be configured to do the reverse. -This cop can be customized allowed methods with `AllowedMethods`. -By default, there are no methods to allowed. +This cop's allowed methods can be customized with `AllowedMethods`. +By default, there are no allowed methods. This cop disregards `#nonzero?` as its value is truthy or falsey, but not `true` and `false`, and thus not always interchangeable with diff --git a/config/contents/style/quoted_symbols.md b/config/contents/style/quoted_symbols.md index b756462b..2e145ee6 100644 --- a/config/contents/style/quoted_symbols.md +++ b/config/contents/style/quoted_symbols.md @@ -4,7 +4,7 @@ cop is not enabled, the default `EnforcedStyle` is `single_quotes`. String interpolation is always kept in double quotes. -Note: `Lint/SymbolConversion` can be used in parallel to ensure that symbols +NOTE: `Lint/SymbolConversion` can be used in parallel to ensure that symbols are not quoted that don't need to be. This cop is for configuring the quoting style to use for symbols that require quotes. diff --git a/config/contents/style/redundant_condition.md b/config/contents/style/redundant_condition.md index acdfb1d3..c27c1e21 100644 --- a/config/contents/style/redundant_condition.md +++ b/config/contents/style/redundant_condition.md @@ -7,7 +7,6 @@ Checks for unnecessary conditional expressions. # good a = b || c -### Example: # bad if b b diff --git a/config/contents/style/redundant_file_extension_in_require.md b/config/contents/style/redundant_file_extension_in_require.md index fa04126e..8f69e7f9 100644 --- a/config/contents/style/redundant_file_extension_in_require.md +++ b/config/contents/style/redundant_file_extension_in_require.md @@ -1,7 +1,7 @@ Checks for the presence of superfluous `.rb` extension in the filename provided to `require` and `require_relative`. -Note: If the extension is omitted, Ruby tries adding '.rb', '.so', +NOTE: If the extension is omitted, Ruby tries adding '.rb', '.so', and so on to the name until found. If the file named cannot be found, a `LoadError` will be raised. There is an edge case where `foo.so` file is loaded instead of a `LoadError` diff --git a/config/contents/style/redundant_interpolation_unfreeze.md b/config/contents/style/redundant_interpolation_unfreeze.md new file mode 100644 index 00000000..5e9676db --- /dev/null +++ b/config/contents/style/redundant_interpolation_unfreeze.md @@ -0,0 +1,14 @@ +Before Ruby 3.0, interpolated strings followed the frozen string literal +magic comment which sometimes made it necessary to explicitly unfreeze them. +Ruby 3.0 changed interpolated strings to always be unfrozen which makes +unfreezing them redundant. + +### Example: + # bad + +"#{foo} bar" + + # bad + "#{foo} bar".dup + + # good + "#{foo} bar" diff --git a/config/contents/style/return_nil_in_predicate_method_definition.md b/config/contents/style/return_nil_in_predicate_method_definition.md index 87b2416a..6c339fc9 100644 --- a/config/contents/style/return_nil_in_predicate_method_definition.md +++ b/config/contents/style/return_nil_in_predicate_method_definition.md @@ -1,4 +1,5 @@ -Checks if `return` or `return nil` is used in predicate method definitions. +Checks for predicate method definitions that return `nil`. +A predicate method should only return a boolean value. ### Safety: @@ -27,6 +28,24 @@ from `nil` to `false` could potentially lead to incompatibility issues. do_something? end + # bad + def foo? + if condition + nil + else + true + end + end + + # good + def foo? + if condition + false + else + true + end + end + ### Example: AllowedMethods: ['foo?'] # good def foo? diff --git a/config/contents/style/safe_navigation.md b/config/contents/style/safe_navigation.md index e8f50ad5..f817302f 100644 --- a/config/contents/style/safe_navigation.md +++ b/config/contents/style/safe_navigation.md @@ -12,9 +12,14 @@ of the method is. If this is converted to safe navigation, `foo&.bar` can start returning `nil` as well as what the method returns. -The default for `MaxChainLength` is `2` +The default for `MaxChainLength` is `2`. We have limited the cop to not register an offense for method chains -that exceed this option is set. +that exceed this option's value. + +NOTE: This cop will recognize offenses but not autocorrect code when the +right hand side (RHS) of the `&&` statement is an `||` statement +(eg. `foo && (foo.bar? || foo.baz?)`). It can be corrected +manually by removing the `foo &&` and adding `&.` to each `foo` on the RHS. ### Safety: diff --git a/config/contents/style/safe_navigation_chain_length.md b/config/contents/style/safe_navigation_chain_length.md new file mode 100644 index 00000000..89d04d95 --- /dev/null +++ b/config/contents/style/safe_navigation_chain_length.md @@ -0,0 +1,19 @@ +Enforces safe navigation chains length to not exceed the configured maximum. +The longer the chain is, the harder it becomes to track what on it could be +returning `nil`. + +There is a potential interplay with `Style/SafeNavigation` - if both are enabled +and their settings are "incompatible", one of the cops will complain about what +the other proposes. + +E.g. if `Style/SafeNavigation` is configured with `MaxChainLength: 2` (default) +and this cop is configured with `Max: 1`, then for `foo.bar.baz if foo` the former +will suggest `foo&.bar&.baz`, which is an offense for the latter. + +### Example: Max: 2 (default) + # bad + user&.address&.zip&.upcase + + # good + user&.address&.zip + user.address.zip if user diff --git a/config/contents/style/select_by_regexp.md b/config/contents/style/select_by_regexp.md index 1a97bf1b..056020d6 100644 --- a/config/contents/style/select_by_regexp.md +++ b/config/contents/style/select_by_regexp.md @@ -23,7 +23,7 @@ Additionally, the cop cannot guarantee that the receiver of so the correction may not be actually equivalent. ### Example: - # bad (select or find_all) + # bad (select, filter, or find_all) array.select { |x| x.match? /regexp/ } array.select { |x| /regexp/.match?(x) } array.select { |x| x =~ /regexp/ } diff --git a/config/contents/style/send_with_literal_method_name.md b/config/contents/style/send_with_literal_method_name.md index 613420a0..ff6b1330 100644 --- a/config/contents/style/send_with_literal_method_name.md +++ b/config/contents/style/send_with_literal_method_name.md @@ -2,6 +2,19 @@ Detects the use of the `public_send` method with a literal method name argument. Since the `send` method can be used to call private methods, by default, only the `public_send` method is detected. +NOTE: Writer methods with names ending in `=` are always permitted because their +behavior differs as follows: + +```ruby +def foo=(foo) + @foo = foo + 42 +end + +self.foo = 1 # => 1 +send(:foo=, 1) # => 42 +``` + ### Safety: This cop is not safe because it can incorrectly detect based on the receiver. diff --git a/config/contents/style/super_arguments.md b/config/contents/style/super_arguments.md index e5ff00f2..4795b0b1 100644 --- a/config/contents/style/super_arguments.md +++ b/config/contents/style/super_arguments.md @@ -1,5 +1,21 @@ -Checks for redundant argument forwarding when calling super -with arguments identical to the method definition. +Checks for redundant argument forwarding when calling super with arguments identical to +the method definition. + +Using zero arity `super` within a `define_method` block results in `RuntimeError`: + +```ruby +def m + define_method(:foo) { super() } # => OK +end + +def m + define_method(:foo) { super } # => RuntimeError +end +``` + +Furthermore, any arguments accompanied by a block may potentially be delegating to +`define_method`, therefore, `super` used within these blocks will be allowed. +This approach might result in false negatives, yet ensuring safe detection takes precedence. ### Example: # bad diff --git a/config/contents/style/while_until_do.md b/config/contents/style/while_until_do.md index 51f09080..5c9df77d 100644 --- a/config/contents/style/while_until_do.md +++ b/config/contents/style/while_until_do.md @@ -12,8 +12,6 @@ Checks for uses of `do` in multi-line `while/until` statements. do_something(x.pop) end -### Example: - # bad until x.empty? do do_something(x.pop) diff --git a/config/contents/style/while_until_modifier.md b/config/contents/style/while_until_modifier.md index bc2f6524..fb5efb84 100644 --- a/config/contents/style/while_until_modifier.md +++ b/config/contents/style/while_until_modifier.md @@ -11,7 +11,6 @@ configured in the `Layout/LineLength` cop. # good x += 1 while x < 10 -### Example: # bad until x > 10 x += 1 diff --git a/lib/cc/engine/file_list_resolver.rb b/lib/cc/engine/file_list_resolver.rb index da3fdb96..c5188f7e 100644 --- a/lib/cc/engine/file_list_resolver.rb +++ b/lib/cc/engine/file_list_resolver.rb @@ -3,7 +3,7 @@ module CC module Engine class FileListResolver - def initialize(root:, engine_config: {}, config_store:) + def initialize(root:, config_store:, engine_config: {}) @root = root @include_paths = engine_config["include_paths"] || ["./"] @config_store = config_store @@ -25,11 +25,9 @@ def expanded_list def absolute_include_paths @include_paths.map do |path| - begin - Pathname.new(path).realpath.to_s - rescue Errno::ENOENT - nil - end + Pathname.new(path).realpath.to_s + rescue Errno::ENOENT + nil end.compact end diff --git a/lib/cc/engine/fingerprint.rb b/lib/cc/engine/fingerprint.rb index f30cdabe..622bd54f 100644 --- a/lib/cc/engine/fingerprint.rb +++ b/lib/cc/engine/fingerprint.rb @@ -15,7 +15,7 @@ class Fingerprint Metrics/PerceivedComplexity ].freeze - URL_REGEX = / \(https?\:.+\)/ + URL_REGEX = / \(https?:.+\)/ LINES_REGEX = / \[.+\]$/ def initialize(path, cop_name, message) diff --git a/lib/cc/engine/issue.rb b/lib/cc/engine/issue.rb index 1e860d10..033f5b27 100644 --- a/lib/cc/engine/issue.rb +++ b/lib/cc/engine/issue.rb @@ -5,7 +5,7 @@ module CC module Engine class Issue < SimpleDelegator - MULTIPLIER_REGEX = %r{\[([\d\.]+)\/([\d\.]+)\]} + MULTIPLIER_REGEX = %r{\[([\d.]+)/([\d.]+)\]} DEFAULT_REMEDIATION_POINTS = 50_000 DEFAULT_BASE_POINTS = 200_000 DEFAULT_OVERAGE_POINTS = 50_000 @@ -18,7 +18,7 @@ def initialize(issue, path, cop_list: nil) end # rubocop:disable Metrics/MethodLength - def to_json + def to_json(*_args) hash = { type: "Issue", check_name: check_name, @@ -38,6 +38,7 @@ def to_json hash.to_json end + # rubocop:enable Metrics/MethodLength def check_name "Rubocop/#{cop_name}" diff --git a/lib/cc/engine/source_file.rb b/lib/cc/engine/source_file.rb index 31be980a..5b721239 100644 --- a/lib/cc/engine/source_file.rb +++ b/lib/cc/engine/source_file.rb @@ -11,7 +11,7 @@ def initialize(config_store:, io:, path:, root:) end def inspect - rubocop_team.inspect_file(processed_source).each do |offense| + rubocop_team.investigate(processed_source).offenses.each do |offense| next if offense.disabled? io.print Issue.new(offense, display_path).to_json @@ -26,7 +26,7 @@ def inspect def processed_source processed_source = RuboCop::ProcessedSource.from_file(path, target_ruby_version) processed_source.config = config_store if processed_source.respond_to?(:config=) - processed_source.registry = RuboCop::Cop::Cop.registry if processed_source.respond_to?(:registry=) + processed_source.registry = RuboCop::Cop::Registry.global if processed_source.respond_to?(:registry=) processed_source end @@ -35,7 +35,7 @@ def target_ruby_version end def rubocop_team - RuboCop::Cop::Team.new(RuboCop::Cop::Cop.registry, config_store, display_cop_names: false) + RuboCop::Cop::Team.mobilize(RuboCop::Cop::Registry.global, config_store, display_cop_names: false) end def display_path diff --git a/spec/cc/engine/category_parser_spec.rb b/spec/cc/engine/category_parser_spec.rb index ca3ed798..9efb0bb6 100644 --- a/spec/cc/engine/category_parser_spec.rb +++ b/spec/cc/engine/category_parser_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "cc/engine/category_parser" diff --git a/spec/cc/engine/content_resolver_spec.rb b/spec/cc/engine/content_resolver_spec.rb index 84d45565..77275555 100644 --- a/spec/cc/engine/content_resolver_spec.rb +++ b/spec/cc/engine/content_resolver_spec.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + require "spec_helper" require "rubocop" require "cc/engine/content_resolver" module CC::Engine describe ContentResolver do - cops = RuboCop::Cop::Cop.all + cops = RuboCop::Cop::Registry.all # The more docs the better -- feel free to unwhitelist cops and add readups whitelist = File.read("./spec/support/currently_undocumented_cops.txt").lines.map(&:chomp) @@ -17,7 +19,7 @@ module CC::Engine context "for #{cop.name}" do if whitelist.include?(cop.name) it "has no content" do - expect(ContentResolver.new(cop.name).content).to eq false + expect(ContentResolver.new(cop.name).content).to be false end else it "has content" do diff --git a/spec/cc/engine/file_list_resolver_spec.rb b/spec/cc/engine/file_list_resolver_spec.rb index 80edcb70..44c8f81a 100644 --- a/spec/cc/engine/file_list_resolver_spec.rb +++ b/spec/cc/engine/file_list_resolver_spec.rb @@ -1,12 +1,15 @@ +# frozen_string_literal: true + require "spec_helper" require "rubocop" require "cc/engine/file_list_resolver" module CC::Engine describe FileListResolver do - include FilesystemHelpers + include ::FilesystemHelpers before { @code = Dir.mktmpdir } + let(:rubocop_config) { RuboCop::ConfigStore.new } it "uses default include path" do @@ -25,7 +28,7 @@ module CC::Engine create_source_file("bin/some_script", "#!/usr/bin/env ruby") resolver = FileListResolver.new(root: @code, engine_config: {}, config_store: rubocop_config) - expect(resolver.expanded_list).to eq %w[a.rb bin/some_script].map { |fn| Pathname.new(fn).realpath.to_s } + expect(resolver.expanded_list).to eq(%w[a.rb bin/some_script].map { |fn| Pathname.new(fn).realpath.to_s }) end end diff --git a/spec/cc/engine/fingerprint_spec.rb b/spec/cc/engine/fingerprint_spec.rb index f99b4a2f..4dd5a0d5 100644 --- a/spec/cc/engine/fingerprint_spec.rb +++ b/spec/cc/engine/fingerprint_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "cc/engine/fingerprint" @@ -21,7 +23,7 @@ module CC::Engine computed = Fingerprint.new(path, cop_name, message).compute - expect(computed).not_to be + expect(computed).to be_nil end it "computes same fingerprint regardles of message url detail" do diff --git a/spec/cc/engine/issue_spec.rb b/spec/cc/engine/issue_spec.rb index 70ceec94..25ca0e1a 100644 --- a/spec/cc/engine/issue_spec.rb +++ b/spec/cc/engine/issue_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "cc/engine/issue" require "ostruct" diff --git a/spec/cc/engine/rubocop_spec.rb b/spec/cc/engine/rubocop_spec.rb index 5a7a0352..f53fe930 100644 --- a/spec/cc/engine/rubocop_spec.rb +++ b/spec/cc/engine/rubocop_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "cc/engine/rubocop" require "ostruct" @@ -5,7 +7,7 @@ module CC::Engine describe Rubocop do - include RubocopRunner + include ::RubocopRunner describe "#run" do it "analyzes ruby files using rubocop" do @@ -150,9 +152,9 @@ def method end it "handles different locations properly" do - pseudo_source_range_klass = RuboCop::Cop::Offense::const_get(:PseudoSourceRange) + pseudo_source_range_klass = RuboCop::Cop::Offense.const_get(:PseudoSourceRange) - allow_any_instance_of(RuboCop::Cop::Team).to receive(:inspect_file).and_return( + allow_any_instance_of(RuboCop::Cop::Team).to receive_message_chain(:investigate, :offenses).and_return( [ OpenStruct.new( location: pseudo_source_range_klass.new( @@ -230,7 +232,7 @@ def method i["description"] == "unexpected token tCOLON" end - expect(issue).to be nil + expect(issue).to be_nil end it "includes Ruby files even if they don't end with .rb" do diff --git a/spec/cc/engine/source_file_spec.rb b/spec/cc/engine/source_file_spec.rb deleted file mode 100644 index e69de29b..00000000 diff --git a/spec/rubocop/config_patch_spec.rb b/spec/rubocop/config_patch_spec.rb index 292c30a3..e39c5999 100644 --- a/spec/rubocop/config_patch_spec.rb +++ b/spec/rubocop/config_patch_spec.rb @@ -4,7 +4,6 @@ module CC::Engine describe "Rubocop config patch" do - it "prevents config from raising on obsolete cops" do config = RuboCop::Config.new( { @@ -19,6 +18,7 @@ module CC::Engine expect { config.validate }.to_not raise_error end.to output(//).to_stderr end + it "warns about obsolete cops" do config = RuboCop::Config.new( { @@ -49,7 +49,6 @@ module CC::Engine ".rubocop.yml" ) - expected = <<~EOM The `Style/TrailingComma` cop has been removed. Please use `Style/TrailingCommaInArguments`, `Style/TrailingCommaInArrayLiteral` and/or `Style/TrailingCommaInHashLiteral` instead. (obsolete configuration found in .rubocop.yml, please update it) diff --git a/spec/rubocop/cop_patches_spec.rb b/spec/rubocop/cop_patches_spec.rb index 021ef38e..3ead777f 100644 --- a/spec/rubocop/cop_patches_spec.rb +++ b/spec/rubocop/cop_patches_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + require "spec_helper" module CC::Engine describe "Rubocop cops patch" do - include RubocopRunner + include ::RubocopRunner describe "Metrics::AbcSize patch" do it "includes complete method body for cyclomatic complexity issue" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0a03b9e4..67e4125a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rspec" Dir.glob("spec/support/**/*.rb").each(&method(:load)) diff --git a/spec/support/filesystem_helpers.rb b/spec/support/filesystem_helpers.rb index 426a8cbc..143349de 100644 --- a/spec/support/filesystem_helpers.rb +++ b/spec/support/filesystem_helpers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module FilesystemHelpers def create_source_file(path, content) abs_path = File.join(@code, path) diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index be553e8b..eec7d2fd 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rspec/expectations' RSpec::Matchers.define :include_fingerprint do |fingerprint| diff --git a/spec/support/rubocop_runner.rb b/spec/support/rubocop_runner.rb index 0ef47e5d..417b912a 100644 --- a/spec/support/rubocop_runner.rb +++ b/spec/support/rubocop_runner.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + require "cc/engine/rubocop" require "tmpdir" module RubocopRunner def self.included(example_group) - example_group.include FilesystemHelpers + example_group.include ::FilesystemHelpers example_group.around do |example| Dir.mktmpdir do |code| @code = code